Why does std :: map emplace need a copy constructor on gcc?

The following code compiles well in the Visual Studio Visual C ++ 19.0 compiler, but gcc 5.4.0 complains that the copy constructor is private.

#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; } 

Error message:

 'CMyClass::CMyClass(const CMyClass&)' is private 

Shouldn't I copy exactly what emplace ? Did I miss something?

+5
source share
2 answers

This is not valid in C ++ 11 as published.

The C ++ 11 standard depicts two pair constructors with two parameters:

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

If the first one is selected, you are doomed for obvious reasons.

The second overload is not involved in overload resolution if, as appropriate here, " V implicitly converted to second_type ". Here V is int , second_type is CMyClass . Is an int implicitly convertible to CMyClass ? No, because CMyClass x = some_int; declaration CMyClass x = some_int; is not correct, as in C ++ 11, which declares structurally temporary from some_int , and then translates it to x, but CMyClass cannot be moved.

Additional GCC overloads added - as permitted - have similar limitations.


C ++ 17 has significantly updated the restrictions on pair constructors, which have a side effect that allows your code to work. The developers saw this as a retroactive bug fix, so GCC 6 accepts your code.

+3
source

GCC 5.4.0 checks if types can convert only when overload is enabled:

  // 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) { } 

While later versions of GCC check if this is constructive:

 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) { } 

In particular, _PCCP is an alias for _PCC<true, _T1, _T2> . _PCC is a feature class containing this function:

 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 } 
+2
source

Source: https://habr.com/ru/post/1269105/


All Articles