c++ - 这个不可复制的 map 是否合法 c++11? GCC 4.7 和 MSVS 2010 允许它。 Clang 3.1 没有

标签 c++ c++11 clang move-semantics deleted-functions

我创建了一个不可复制的 map ,我无法使用 clang 对其进行编译。由于 clang 非常符合标准,我想知道我的代码是否合法。 MSVS 2010 和 GCC 4.7 编译此代码时没有警告或错误。

附上完整代码:有问题的行是main的最后一行。

= delete 需要删除 MSVS 2010

#include <utility>
#include <iostream>
#include <map>

template<typename Key_t, typename Value_t, typename Compare_t = std::less<Key_t> >
class non_copyable_map : public std::map<Key_t,Value_t,Compare_t>
{
  typedef std::map<Key_t,Value_t,Compare_t> BaseType;

  public:
    non_copyable_map() { } 

    non_copyable_map(non_copyable_map&& t) : BaseType(std::move(t)) {}   

    non_copyable_map& operator = (non_copyable_map&& t)
    {   
      if ( this != &t )
      {   
        std::swap<BaseType>(*this,t);
      }   
      return *this;
    }   

  private:
    non_copyable_map(const non_copyable_map&) = delete;
    non_copyable_map& operator = (const non_copyable_map&) = delete;
};

int main(int argc, char* argv[])
{
  non_copyable_map<int, non_copyable_map<int, int> > nestedMap;
  non_copyable_map<int,int> inner;
  inner[3]=4;
  nestedMap[2] = std::move(inner); // THIS LINE CAUSES CLANG PROBLEMS
}

使用 clang++-mp-3.1 -std=c++0x -stdlib=libc++ MapOfMaps.cpp 时的错误信息是:

In file included from MapOfMaps.cpp:2:
In file included from /usr/include/c++/v1/iostream:40:
In file included from /usr/include/c++/v1/istream:156:
In file included from /usr/include/c++/v1/ostream:134:
In file included from /usr/include/c++/v1/bitset:118:
/usr/include/c++/v1/__bit_reference:26:26: error: no type named '__storage_type' in
      'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
      int, int> > >'
    typedef typename _C::__storage_type    __storage_type;
            ~~~~~~~~~~~~~^~~~~~~~~~~~~~
MapOfMaps.cpp:21:25: note: in instantiation of template class
      'std::__1::__bit_reference<std::__1::map<int, int, std::__1::less<int>,
      std::__1::allocator<std::__1::pair<const int, int> > > >' requested here
                                std::swap<BaseType>(*this,t);
                                                    ^
MapOfMaps.cpp:36:15: note: in instantiation of member function 'non_copyable_map<int, int,
      std::__1::less<int> >::operator=' requested here
        nestedMap[2] = std::move(inner);
                     ^
In file included from MapOfMaps.cpp:2:
In file included from /usr/include/c++/v1/iostream:40:
In file included from /usr/include/c++/v1/istream:156:
In file included from /usr/include/c++/v1/ostream:134:
In file included from /usr/include/c++/v1/bitset:118:
/usr/include/c++/v1/__bit_reference:27:26: error: no type named '__storage_pointer' in
      'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
      int, int> > >'
    typedef typename _C::__storage_pointer __storage_pointer;
            ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
/usr/include/c++/v1/__bit_reference:33:25: error: no type named '__self' in
      'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
      int, int> > >'
    friend typename _C::__self;
           ~~~~~~~~~~~~~^~~~~~
In file included from MapOfMaps.cpp:3:
In file included from /usr/include/c++/v1/map:338:
/usr/include/c++/v1/__tree:1291:14: error: overload resolution selected deleted operator '='
    __pair3_ = _STD::move(__t.__pair3_);
    ~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/v1/__tree:1308:9: note: in instantiation of member function
      'std::__1::__tree<std::__1::pair<int, int>, std::__1::__map_value_compare<int, int,
      std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<int, int> >
      >::__move_assign' requested here
        __move_assign(__t, true_type());
        ^
/usr/include/c++/v1/__tree:1353:5: note: in instantiation of member function
      'std::__1::__tree<std::__1::pair<int, int>, std::__1::__map_value_compare<int, int,
      std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<int, int> >
      >::__move_assign' requested here
    __move_assign(__t, integral_constant<bool,
    ^
/usr/include/c++/v1/map:736:21: note: in instantiation of member function
      'std::__1::__tree<std::__1::pair<int, int>, std::__1::__map_value_compare<int, int,
      std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<int, int> > >::operator='
      requested here
            __tree_ = _STD::move(__m.__tree_);
                    ^
/usr/include/c++/v1/type_traits:2342:9: note: in instantiation of member function
      'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
      int, int> > >::operator=' requested here
    __x = _STD::move(__y);
        ^
MapOfMaps.cpp:21:5: note: in instantiation of function template specialization
      'std::__1::swap<std::__1::map<int, int, std::__1::less<int>,
      std::__1::allocator<std::__1::pair<const int, int> > > >' requested here
                                std::swap<BaseType>(*this,t);
                                ^
MapOfMaps.cpp:36:15: note: in instantiation of member function 'non_copyable_map<int, int,
      std::__1::less<int> >::operator=' requested here
        nestedMap[2] = std::move(inner);
                     ^
/usr/include/c++/v1/memory:1918:7: note: candidate function (the implicit copy assignment
      operator) has been explicitly deleted
class __compressed_pair
      ^
4 errors generated.

最佳答案

这可能是 clang 或 libc++ 错误(很可能是 libc++)。我不会用 tip-of-trunk 工具复制你的症状。最新的 libc++ header 是 here .这有点摸不着头脑,但试试这个:

    swap(static_cast<BaseType&>(*this),static_cast<BaseType&>(t));

看来您正在纠结这个 swap<__bit_reference> :

template <class _Cp, class _Dp>
_LIBCPP_INLINE_VISIBILITY inline
void
swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT

这与 map 无关。它恰好在范围内。

关于c++ - 这个不可复制的 map 是否合法 c++11? GCC 4.7 和 MSVS 2010 允许它。 Clang 3.1 没有,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9122065/

相关文章:

c++ - 如何使用私有(private)构造函数 C++ 测试私有(private)成员

c++ - 在参数中移出的智能指针上调用方法是否安全?

c++ - 标准线程库与 Boost 相比如何?

c++ - 防止 clang 扩展聚合类型的参数?

c++ - 我怎样才能初始化这个结构?

c++ - 通过引用传递数据以构建它

c++ - 如何使函数接受任意数量的参数而不使用 f(...)?

c++ - 创建一个像 std::integral_constant 这样的容器

c++ - 如何实现对 std::array 的绑定(bind)检查?

c++ - 链接器命令失败,sdl