为什么std :: map \ templace需要gcc上的拷贝构造函数?

时间:2017-06-22 12:33:24

标签: c++ c++11 gcc

以下代码在Visual Studio的Visual C ++ 19.0编译器上编译得很好,但是gcc 5.4.0抱怨复制构造函数是私有的。

#include <map>

class CMyClass
{
public:
  CMyClass(int) {};
private:
  CMyClass(const CMyClass&); // I want to avoid copy construction
};

int main()
{
  std::map<int, CMyClass> mymap;
  mymap.emplace(0, 0);

  return 0;
}

错误讯息:

‘CMyClass::CMyClass(const CMyClass&)’ is private

是不是完全避免副本emplace的副本?我错过了什么吗?

2 个答案:

答案 0 :(得分:3)

这在已发布的C ++ 11中无效。

C ++ 11标准描述了两个带有两个参数的pair构造函数:

pair(const T1& x, const T2& y);
template<class U, class V> pair(U&& x, V&& y);

如果第一个被选中,你就注定会出于显而易见的原因。

第二次重载不参与重载决策,如果相关的话,&#34; V不能隐式转换为second_type&#34;。此处Vintsecond_typeCMyClassint是否可以隐式转换为CMyClass?不,因为声明CMyClass x = some_int;格式不正确,就像在C ++ 11中一样,声明从CMyClass概念性地构造some_int临时,然后将其移动到x,但是{{1无法移动。

GCC增加的额外重载 - 如果允许的话 - 也有类似的限制。

C ++ 17大大改进了对CMyClass构造函数的约束,这会产生允许代码工作的副作用。实施者将此视为追溯性缺陷修复,这就是GCC 6接受您的代码的原因。

答案 1 :(得分:2)

GCC 5.4.0仅在启用有问题的重载时检查类型是否可转换:

  // DR 811.
  template<class _U1, class = typename
       enable_if<is_convertible<_U1, _T1>::value>::type>
constexpr pair(_U1&& __x, const _T2& __y)
: first(std::forward<_U1>(__x)), second(__y) { }

而更新版本的GCC会检查它是否可移动构建:

288       template<typename _U1, typename
289            enable_if<_PCCP::template
290                _MoveCopyPair<true, _U1, _T2>(),
291                          bool>::type=true>
292        constexpr pair(_U1&& __x, const _T2& __y)
293        : first(std::forward<_U1>(__x)), second(__y) { }

特别是_PCCP_PCC<true, _T1, _T2>的别名。 _PCC是一个包含此函数的traits类:

138       template <bool __implicit, typename _U1, typename _U2>
139       static constexpr bool _MoveCopyPair()
140       {
141     using __do_converts = __and_<is_convertible<_U1&&, _T1>,
142                   is_convertible<const _U2&, _T2>>;
143     using __converts = typename conditional<__implicit,
144                        __do_converts,
145                        __not_<__do_converts>>::type;
146     return __and_<is_constructible<_T1, _U1&&>,
147               is_constructible<_T2, const _U2&&>,
148               __converts
149               >::value;
150       }