使用std :: map <K,V>其中V没有可用的默认构造函数

BCS*_*BCS 42 c++ stl map compile-time

我有一个符号表实现为std::map.对于该值,无法通过默认构造函数合法地构造值类型的实例.但是,如果我不提供默认构造函数,我会收到编译器错误,如果我使构造函数断言,我的程序编译得很好,但map<K,V>::operator []如果我尝试使用它来添加新成员,则会崩溃.

有没有办法让C++ map[k]在编译时禁止作为l值(同时允许它作为r值)?


顺便说一句:我知道我可以使用插入地图Map.insert(map<K,V>::value_type(k,v)).


编辑:有几个人提出的解决方案相当于改变值的类型,以便映射可以构造一个而不调用默认构造函数.这与我想要的完全相反,因为它将错误隐藏到以后.如果我愿意这样做,我可以简单地从构造函数中删除断言.我想要的是让错误更快发生; 在编译时.然而,似乎没有办法区分r值和l值使用,operator[]所以看起来我想要的不能这样做,所以我只需要免除一起使用它.

小智 42

您不能让编译器区分operator []的两种用法,因为它们是相同的.Operator []返回一个引用,因此赋值版本只是分配给该引用.

就个人而言,除了快速而肮脏的演示代码之外,我从不使用operator []作为地图.请改用insert()和find().请注意,make_pair()函数使插入更易于使用:

m.insert( make_pair( k, v ) );
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,您也可以这样做

m.emplace( k, v );
m.emplace( piecewise_construct, make_tuple(k), make_tuple(the_constructor_arg_of_v) );
Run Code Online (Sandbox Code Playgroud)

即使没有提供复制/移动构造函数.

  • 如果您有C++ 11或更高版本,我建议使用初始化列表:`m.insert({k,v});`.使用`V map :: at(K key)`来检索值,例如`int val = m.at("important_value")` (2认同)

sud*_*ash 7

使用map<K,V>::at(). map<K,V>::operator []如果提供的键不存在,将尝试默认构造一个元素。


ari*_*els 5

V没有默认构造函数,因此您无法真正期望 可用.std::map<K,V> std::map<K,V>::operator[]

A std::map<K, boost::optional<V> > 确实具有mapped_type默认构造,并且可能具有您想要的语义.请参阅Boost.Optional文档的细节(你需要了解他们的).

  • 使用std :: map的非默认构造类型是完全可以的 - 你不能使用operator []. (2认同)