c++ - 为什么缩小转换不能防止这个不正确类型的 map.insert() 失败?
问题描述
背景
将 a 插入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};
or static_cast<uint64_t>(-42);
) - 因此没有警告。您对此无能为力,因为无法明确给出构造函数模板的模板参数,如此处所述。
[...]如何使它导致错误?
使用std::make_pair
且不依赖模板参数推导:
auto p = std::make_pair<uint64_t, uint64_t>(-42, -42);
// Be explicit: ^^^^^^^^ ^^^^^^^^
当您使用-Wsign-conversion
(重要:-Wconversion
不会引用它!)编译上面的代码片段时,它会给您一个警告(显然,添加-Werror
以将其视为错误)。
的问题是相同的,请参见此处std::map::insert
的重载 (2) 。这会将任何可用的给定参数转换为对象,并将其视为任何转换都是调用者的意图。有趣的是,a 上的等效成员函数受到更多限制。所以这被抓住了:value_type
std::set
std::set<uint64_t> s;
s.insert(-42); // complains with -Wsign-conversion
推荐阅读
- c - 为什么 C11 全局和局部静态断言的行为不同?
- kotlin - 在没有析构函数/生命周期的类中启动协程
- c# - 如何使用 SimpleInjector 注册 CustomContext(DbConnection 连接,DbCompiledModel 编译模型)?
- spring-boot - Spring boot 2 + Microsoft AD 身份验证 + 未找到 userPassword 属性
- javascript - 在 react native 中从 firebase firestore 收集数据返回未定义的承诺之外
- fragment-shader - 在 Godot 片段着色器中绘制矩形的问题
- python - 如何在python中编写两个相邻的函数?
- r - 计算 R tidyverse 环境中 2 个列表元素的所有组合的多个 t 检验
- javascript - PWA 应用可以发布到应用商店和游戏商店吗
- nlp - 在 nlplab Brat 注释工具中创建每个用户工作区