考虑以下代码:什么是对std :: map <K, V> :: mapped_type的限制?
#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 ++以及铛++时,他们使用libstdc++
版本低于4.8失败编译。确切的错误信息铛++吐出的是:
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[]
的合同),没有任何移动/复制构造函数或operator=
?
哪个实现符合?如果有的话,标准对std::map<K, V>::mapped_type
有什么看法?
[编译正常](http://cpp.sh/437p) – CoryKramer
23.2.4.7 has'关联容器满足分配器感知容器(23.2.1)的所有要求,除了映射和多映射的 ,表96中对value_type的要求改为适用于key_type 和mapped_type。 [注:例如,在一些情况下为key_type和mapped_type需要是 CopyAssignable即使相关VALUE_TYPE,对<常量为key_type,mapped_type>,是不是 CopyAssignable。 - 注意]'可能是导致问题的原因。 – NathanOliver
@CoryKramer似乎正在使用最近的'libstdC++',我知道它编译好。 –