为什么缩小转换范围不能防止错误类型的map.insert()失败
Why is narrowing conversion not preventing this map.insert() of an incorrect type from failing?
背景
当将std::pair<uint64_t, uint64_t>
插入C++std::map<uint64_t, int>
时,编译器和程序都不会抱怨,即使传递的值对于数据类型uint64_t
是不可能的。
换句话说,std::pair<uint64_t, uint64_t>(2, -2)
的缩小转换不起作用,并且默认为映射的类型std::map<uint64_t, int>
代码
当我用g++ -Wall -Wconversion -Wextra -pedantic test/test_wrong_insert.cpp && ./a.out
编译和执行以下代码时:
#include<map>
#include<iostream>
void print_map(std::map<uint64_t, int> & m){
std::cout << "The map is now: {";
for (const auto & n: m){
std::cout << '(' << n.first << ',' << n.second << ") ";
}
std::cout << "}n";
}
int main(){
std::map<uint64_t, int> m;
auto ret = m.insert(std::pair<uint64_t, uint64_t>(2,-2));
std::cout << "Tried to insert std::pair<uint64_t, uint64_t>(2,-2). ";
std::cout << "Return: " << ret.second << 'n';
print_map(m);
}
结果
这是输出:
Tried to insert std::pair<uint64_t, uint64_t>(2,-2). Return: 1
The map is now: {(2,-2) }
问题
为什么std::pair<uint64_t,uint64_t> x{-1,-2}
不会产生错误,以及如何使其导致错误?
为什么
std::pair<uint64_t,uint64_t> x{-1,-2}
不产生错误?
这是由构造函数模板引起的,当两个参数都可以用于构造uint64_t
(或实例化std::pair
的任何类型)的对象时,该模板会参与重载解析。它是std::pair
构造函数列表中的重载(3),其模板参数推导导致转换被视为有意(如auto n = uint64_t{-42};
或static_cast<uint64_t>(-42);
),因此没有警告。你对此无能为力,因为构造函数模板的模板参数不能显式给定,正如这里所解释的那样。
[…]如何使其引起错误?
使用std::make_pair
,不要依赖模板参数推导:
auto p = std::make_pair<uint64_t, uint64_t>(-42, -42);
// Be explicit: ^^^^^^^^ ^^^^^^^^
当您使用-Wsign-conversion
编译上面的代码段时(重要的是:-Wconversion
不会cath它!),它会给您一个警告(显然,添加-Werror
会将其视为错误)。
std::map::insert
的问题相同,请参阅此处的过载(2)。这将任何可用的给定参数转换为value_type
对象,并将其视为调用方的意图进行的任何转换。有趣的是,std::set
上的等价成员函数受到了更多的限制。所以这被抓住了:
std::set<uint64_t> s;
s.insert(-42); // complains with -Wsign-conversion
- 与C++std::map::insert行为相比,C#排序字典的效率
- std::map insert && hyperload 导致复制
- 为什么在以下示例中 std::map::insert 失败?
- map.insert:"Invalid arguments"错误与 pair<enum,vector<*>>
- 为什么缩小转换范围不能防止错误类型的map.insert()失败
- 当 std::map::insert 找到该元素时,它仍构造该对象的实例.我怎样才能阻止这种情况
- std::map::insert exception
- C++错误: map.insert(make_pair(struct, vector<struct>));
- C++std::map.insert()分段错误
- boost::interprocess::map insert 给出:对重载函数的不明确调用
- 为什么返回map.insert().second会引入无法访问的内存
- 如果map.insert失败,如何在不使用bad_alloc的情况下检查其失败
- 为什么编译顺序在使用 std::map::insert() 时有时会导致分段错误
- std::map.insert "could not deduce template argument for..."
- 如何根据插入对的存在来实现不同的“std::map insert()”行为
- Map::insert不起作用
- Std::map insert()提示位置:c++98和c++11的区别
- 在std::map::insert时出现分段错误
- 何时将node_type与std::map::insert一起使用
- 为什么map.insert()方法调用复制构造函数两次?