The following code compiles well on Visual Studio's Visual C++ 19.0 compiler, but gcc 5.4.0 complains about the copy constructor being 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
Isn't avoiding copies exactly what emplace
is for? Am I missing something?
Copy constructor is used to copy a whole existing map and the map to be copied is passed as a single param to the constructor.
The map::emplace() is a built-in function in C++ STL which inserts the key and its element in the map container. It effectively increases the container size by one.
Yes -- when you insert an item into an std::map, you pass it by value, so what it contains is a copy of what you passed.
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 gets chosen, you are doomed for obvious reasons.
The second overload does not participate in overload resolution if, as relevant here, "V
is not implicitly convertible to second_type
". Here, V
is int
, second_type
is CMyClass
. Is int
implicitly convertible to CMyClass
? No, because the declaration CMyClass x = some_int;
is not well-formed, as in C++11 that declaration notionally constructs a CMyClass
temporary from some_int
and then moves it into x, but CMyClass
cannot be moved.
The extra overloads GCC added - as is allowed - have similar constraints.
C++17 substantially revamped the constraints on pair
's constructors, which has the side effect of allowing your code to work. Implementers treated this as a retroactive defect fix, which is why GCC 6 accepts your code.
GCC 5.4.0 is only checking if the types are convertible when enabling the overload in question:
// 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) { }
Whereas more recent versions of GCC checks if it is move constructible:
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 traits class that contains 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 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With