填充std :: map时,"C2593:operator = is ambiguous"

man*_*eak 7 c++ c++11

我有一个std::map我正在尝试初始化初始化列表.我在两个地方以两种不同的方式做到这一点.第一个工作,而另一个工作导致标题中提到的错误.

这是有效的:

void foo() {
    static std::map<std::string, std::string> fooMap =
    {
        { "First", "ABC" },
        { "Second", "DEF" }
    };
}
Run Code Online (Sandbox Code Playgroud)

虽然这个没有:

class Bar {
    public:
        Bar();
    private:
        std::map<std::string, std::string> barMap;
};

Bar::Bar() {
    barMap = { // <-- this is the error line
        { "First", "ABC" },
        { "Second", "DEF" }
    };
}
Run Code Online (Sandbox Code Playgroud)

为什么在尝试初始化类成员时会出现错误,而静态映射有效?目前,我可以通过首先创建一个局部变量然后将其与成员交换来填充成员,如下所示:

Bar::Bar() {
    std::map<std::string, std::string> tmpMap = {
        { "First", "ABC" },
        { "Second", "DEF" }
    };

    barMap.swap(tmpMap);
}
Run Code Online (Sandbox Code Playgroud)

然而,与直接填充成员相比,这感觉相当反直觉.


编辑:这是编译器输出.

Col*_*mbo 12

这是编译器重载解析机制中的错误 - 或其标准库实现.过载分辨率明确指出[over.ics.rank]/3

- 列表初始化序列L1是比列表初始化序列更好的转换序列,L2如果L1转换 std::initializer_list<X>为某些XL2不是.

在这里,Xstd::pair<std::string, std::string>.L1将列表转换为参数

map& operator=( std::initializer_list<value_type> ilist );
Run Code Online (Sandbox Code Playgroud)

同时L2将列表转换为以下函数的参数之一:

map& operator=( map&& other );
map& operator=( const map& other );
Run Code Online (Sandbox Code Playgroud)

这显然不是initializer_lists.


你可以尝试使用

barMap = decltype(barMap){
    { "First", "ABC" },
    { "Second", "DEF" }
};
Run Code Online (Sandbox Code Playgroud)

哪个应该选择移动赋值运算符(使用VC++演示).临时也应该根据复制省略进行优化.