在C ++中,为什么在嵌套的unordered_map上调用函数需要移动构造函数?

时间:2018-02-16 15:48:29

标签: c++ c++11 move-semantics

我有一个嵌套的无序映射,它在C ++ 11中包含一个自定义对象。它看起来与此类似:

std::unordered_map<std::string, std::unordered_map<std::string, CustomClass>>

此自定义类没有移动构造函数,也不能有隐式构造函数。我在尝试分配到这个结构时遇到错误:

storageStruct[string_1][string_2].function(parameter);

由于它进入模板,实际的错误链解释真的很长,但这是我觉得最适用的那个:

候选构造函数(隐式移动构造函数)不可行:需要1个参数,但提供0

我不想移动这个对象,只是简单地调用它的成员函数。我该如何避免这种不必要的举动?

3 个答案:

答案 0 :(得分:5)

如果您请求的密钥没有,

std::unordered_map::operator[]需要无中心地创建一个元素,即值必须是默认的可构造的。移动构造函数只是一个候选者。提供默认构造函数或不使用operator[](您可以使用unordered_map::find查找元素,使用unordered_map::insert来插入元素。)

答案 1 :(得分:2)

它不是试图移动任何东西。模板的特定成员函数可能需要其模板参数类型中的额外行为。 std::unordered_map::operator[]的使用要求封闭类型为DefaultConstructible,因为如果不存在,则指定创建元素。

如果您确定存在string_1string_2,则可以从operator[]更改为at。抛出std::out_of_range而不是创建元素,因此它不需要保持的类型为DefaultConstructible。它也有const重载,而operator[]没有。

如果你不想投掷的可能性(也许你不确定字符串是否存在)那么你可以使用find,正如其他答案所解释的那样。

答案 2 :(得分:1)

  

如何避免这种不必要的举动?

std::unordered_map::operator[]变异容器(如果它不存在则插入一个空元素),所以你应该使用只读接口:

 auto f1 = storageStruct.find( string_1 );
 if( f1 != storageStruct.end() ) {
     auto f2 = f1->second.find( string_2 );
     if( f2 != f1->second.end() )
         f2->second.function( parameter );
 }