2015-07-10 67 views
3

考慮以下代碼:什麼是對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有什麼看法?

+0

[編譯正常](http://cpp.sh/437p) – CoryKramer

+0

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

+0

@CoryKramer似乎正在使用最近的'libstdC++',我知道它編譯好。 –

回答

3

在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.

mapped_typeoperator[]唯一的要求是,它是DefaultInsertable(基本上,可缺省)。如果庫不支持不可複製的mapped_typeoperator[],那麼這是一個錯誤。

+0

[固定爲g ++ 4.8](http://melpon.org/wandbox/permlink/VFonQVeMIqdqecFl) – TemplateRex

+0

@TemplateRex我試圖找到這個gcc的錯誤,但不能。它絕對在4.7.2上失敗。 – Barry

+0

4.7.2太舊,因此有資格舊車換現金 – TemplateRex

相關問題