使用初始化列表构造map<string,string>参数的类对象时编译报错
关于C++初始化列表隐式转换的编译问题
问题场景代码
定义接收const map<string, string>&参数的Map结构体:
#include <map> #include <string> using namespace std; struct Map { Map(const map<string, string>& map) { } };
使用以下代码创建对象时触发编译错误:
string s; Map j({ {s, s} });
编译错误信息
Error C2675 unary '++': '_Iter' does not define this operator or a conversion to a type acceptable to the predefined operator BioAgent C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.36.32532\include\xtree 1259
对比正常运行的情况
- 将map类型改为
map<string, int>,使用{ {s, 1} }创建对象时无编译错误:struct Map { Map(const map<string, int>& map) { } }; // 正常编译 string s; Map j({ {s, 1} }); - 定义同参数的
Test函数,调用Test({ {s, s} })可正常运行:void Test(const map<string, string>& map) {} // 调用正常 string s; Test({ {s, s} });
问题原因
核心原因是C++初始化列表的重载解析优先级规则:
当使用{...}语法初始化类对象时,编译器会优先尝试匹配类的初始化列表构造函数(即接受std::initializer_list<T>的构造函数),只有当类没有这类构造函数时,才会尝试将初始化列表转换为构造函数参数的目标类型(这里是map<string, string>)。
在MSVC的实现中,针对map<string, string>的场景,编译器在解析{ {s, s} }时错误进入了无效重载路径:它没有正确将初始化列表转换为map<string, string>临时对象,而是尝试用初始化列表直接构造某个内部容器结构,进而触发了xtree头文件中迭代器++操作的错误。
另外两种场景正常运行的原因:
map<string, int>的情况:初始化列表中的int字面量类型匹配更直接,编译器正确完成了从初始化列表到map<string, int>的转换,匹配构造函数成功。- 普通函数调用的情况:函数没有对应的初始化列表重载版本,编译器不会优先匹配初始化列表构造逻辑,直接尝试将初始化列表转换为函数参数要求的
const map<string, string>&类型,转换成功后完成调用。
内容的提问来源于stack exchange,提问作者Jay Evans
相关产品推荐
相关产品推荐

