考慮以下代碼:什麼是對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++',我知道它編譯好。 –