对std :: map <k,v =“”> :: mapped_type有什么限制?

时间:2015-07-10 17:50:17

标签: c++ c++11 standards standard-library

考虑以下代码:

#include <iostream>
#include <map>
#include <string>

using namespace std;

class Foo {
  public:
  Foo() {}
  virtual ~Foo() {}

  void DoFoo() { cout << "Foo" << endl; }

  Foo(const Foo&) = delete;
  void operator=(const Foo&) = delete;
};

int main() {
  map<string, Foo> m;
  m["Foo"].DoFoo();
}

当g ++和clang ++使用早于4.8的libstdc++版本时,它们都无法编译。 clang ++吐出的确切错误消息是:

  

包含在/ usr / include / c ++ / 4.6 / iostream中的文件:39:

     

包含在/ usr / include / c ++ / 4.6 / ostream:39:

中的文件      

包含在/ usr / include / c ++ / 4.6 / ios:40:

中的文件      

包含在/ usr / include / c ++ / 4.6 / bits / char_traits.h中的文件:40:

     

包含在/ usr / include / c ++ / 4.6 / bits / stl_algobase.h中的文件:65:

     

/ usr / include / c ++ / 4.6 / bits / stl_pair.h:121:35:错误:调用已删除   'Foo'的构造函数

     

:first(std :: forward&lt; _U1&gt;(__ x)),second(__ y){}

     

^ ~~~

     

/ usr / include / c ++ / 4.6 / bits / stl_pair.h:267:14:注意:在实例化中   函数模板特化'std :: pair,   Foo&gt; :: pair,void&gt;'请求

     

return __pair_type(std :: forward&lt; _T1&gt;(__ x),std :: forward&lt; _T2&gt;(__ y));

     

^

     

/ usr / include / c ++ / 4.6 / bits / stl_map.h:467:29:注意:在实例化中   功能模板专业化   'std :: make_pair,Foo&gt;'请求

     

__ i = insert(__ i,std :: make_pair(std :: move(__ k),mapped_type()));

     

^

     

21:注意:在成员函数'std :: map,Foo的实例化中,   std :: less&gt ;,std :: allocator,Foo&gt; &GT; &gt; :: operator []'在这里请求

     

M [ “富”] DoFoo();

似乎std::pair的构造函数正在尝试使用Foo的复制构造函数,我认为这是公平的,因为Foo没有声明移动构造函数。正如我所料,提供(默认)移动构造函数可以解决问题。

但是,如果使用的libstdc++版本为4.8或更高版本,则编译成功时不会定义移动构造函数。我确信在两种情况下编译器都是相同的,只有libstdc++版本有所不同。 Foo(Foo&&) = delete;也不会影响clang在这种情况下正确编译的能力。

我的问题有几个方面:

为什么旧版本的libstdc++要求移动构造函数是用户提供的,以便使用它而不是复制构造函数?

在较新版本的库中有什么不同,它允许它创建新元素(根据operator[]的合同)而没有任何移动/复制构造函数或operator=

哪个实施符合要求?如果有的话,标准对std::map<K, V>::mapped_type的评价是什么?

1 个答案:

答案 0 :(得分:3)

在C ++ 11中,[map.access]读取:

  

T& operator[](const key_type& x);

     

1 效果:如果地图中没有等效于x的键,请将value_type(x, T())插入地图。

     

2 需要key_type应为CopyInsertable,mapped_type为DefaultInsertable   *此。

     

3 返回:对* this中x对应的mapped_type的引用。

     

4 复杂性:对数。

operator[] mapped_type上的唯一要求是它是DefaultInsertable(基本上是DefaultConstructible)。如果库不支持带有mapped_type的不可复制operator[],那么这是一个错误。