c++ - std::map<K, V>::mapped_type 有什么限制?

标签 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++ 在使用 libstdc++ 时编译失败版本早于 4.8。 clang++ 吐出的确切错误消息是:

In file included from /usr/include/c++/4.6/iostream:39:

In file included from /usr/include/c++/4.6/ostream:39:

In file included from /usr/include/c++/4.6/ios:40:

In file included from /usr/include/c++/4.6/bits/char_traits.h:40:

In file included from /usr/include/c++/4.6/bits/stl_algobase.h:65:

/usr/include/c++/4.6/bits/stl_pair.h:121:35: error: call to deleted constructor of 'Foo'

: first(std::forward<_U1>(__x)), second(__y) { }

^ ~~~

/usr/include/c++/4.6/bits/stl_pair.h:267:14: note: in instantiation of function template specialization 'std::pair, Foo>::pair, void>' requested here

return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));

^

/usr/include/c++/4.6/bits/stl_map.h:467:29: note: in instantiation of function template specialization 'std::make_pair, Foo>' requested here

__i = insert(__i, std::make_pair(std::move(__k), mapped_type()));

^

21 : note: in instantiation of member function 'std::map, Foo, std::less >, std::allocator, Foo> > >::operator[]' requested here

m["Foo"].DoFoo();

好像std::pair的构造函数正在尝试使用 Foo的复制构造函数,我想这很公平,因为 Foo不声明移动构造函数。正如我所料,提供一个(默认)移动构造函数可以解决这个问题。

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

我的问题有几个方面:

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

新版本的库有什么不同,它允许它创建新元素(根据 operator[] 的契约(Contract))而无需任何移动/复制构造函数或 operator=

哪个实现符合要求?标准对 std::map<K, V>::mapped_type 怎么说? ,如果有的话?

最佳答案

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

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

1 Effects: If there is no key equivalent to x in the map, inserts value_type(x, T()) into the map.

2 Requires: key_type shall be CopyInsertable and mapped_type shall be DefaultInsertable into *this.

3 Returns: A reference to the mapped_type corresponding to x in *this.

4 Complexity: Logarithmic.

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

关于c++ - std::map<K, V>::mapped_type 有什么限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31347198/

相关文章:

c++ - 模板运算符 []=

c++ - 为什么我无法阻止不受欢迎的 C 风格强制转换进行编译?

html - onChange 事件在哪个权威规范中有详尽的定义?

c++ - 我可以在 Boost 中使用 std::function (C++11 lambda) 吗?

C++11 统一初始化 : ambiguity between initializer list and multiple-parameter constructors?

html - li 之后的 ul 或 li 内的 ul 或两种情况

c++ - 阻止异步的解决方法?

c++ - QT 5.7 QML - 引用错误 : Class is not defined

c++ - 训练我们自己的分类器

c++ - 带有 CUDA 的 Lambda 表达式