2015-07-10 39 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

相关问题