Weird error - why does the compiler try to call the copy constructor?

I get very strange errors. The compiler seems to want to call the copy constructor for some reason, I don't understand.

(118) std::map<int, layer> xs; (119) xs.begin()->first; // error?! 

layer is not a copied, movable type.

 class layer : public observable { layer(const layer&); layer& operator=(const layer&); public: layer(int index = -1); layer(layer&& other); layer& operator=(layer&& other); //... }; 

For some reason, line 119 made the compiler try to call the copy constructor for std::pair , why?

 1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(131): error C2248: 'layer::layer' : cannot access private member declared in class 'layer' 1> ..\layer.h(55) : see declaration of 'layer::layer' 1> ..\layer.h(53) : see declaration of 'layer' 1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(129) : while compiling class template member function 'std::_Pair_base<_Ty1,_Ty2>::_Pair_base(const std::_Pair_base<_Ty1,_Ty2> &)' 1> with 1> [ 1> _Ty1=const int, 1> _Ty2=layer 1> ] 1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(174) : see reference to class template instantiation 'std::_Pair_base<_Ty1,_Ty2>' being compiled 1> with 1> [ 1> _Ty1=const int, 1> _Ty2=layer 1> ] 1> ..\stage.cpp(119) : see reference to class template instantiation 'std::pair<_Ty1,_Ty2>' being compiled 1> with 1> [ 1> _Ty1=const int, 1> _Ty2=layer 1> ] 

I also tried the following, where it fails.

 (118) std::map<int, layer> xs; (119) auto& t1 = *xs.begin(); (120) auto& t2 = t1.first; // error?! 

What's going on here?

+7
source share
3 answers

This is one of the weird subtleties of template errors. The template code is not code, it is almost close to the scripting language for code generation. You may even have a syntax error in a function that does not necessarily generate a compiler error until that function is used (directly or indirectly) by your code.

In this case, xs.first () caused the generation of std :: map <int, layer> :: iterator, which also requires the generation of std :: pair <int, layer>. The std :: pair implementation by default has a copy constructor that cannot be compiled.

You can get around this with the specialized std :: pair template, which does not have a copy constructor, but then you cannot insert anything into your map. xs [0] = myLayer creates and inserts std :: make_pair <0, myLayer> into your map, which obviously requires a copy of the layer.

Typical solutions for this are changing your type to std :: map <int, std :: shared_ptr <layer →. Copy shared_ptr does not copy the specified object.

+2
source

It depends on where you initialize this element and its first member. If you initialize it as a static member or on the stack without calling the constructor, it will try to call the default constructor (without parameters) and will not be able to access it, since you made it private.

You must explicitly call the public constructor for elements on the map

-one
source

Your example:

 (118) std::map<int, layer> xs; (119) xs.begin()->first; // error?! 

Per http://www.cplusplus.com/reference/stl/map/

 xs.begin() Return iterator to beginning 

... it-> first; // the same as (* it) .first (key value)

therefore

 xs.begin()->first; 

equivalently

 pair<int,layer> piltmp = (*xs.begin()); piltmp.first; 

Et voila. A copy of the pair was created on the map. This is due to the creation of a copy of the layer.

(This would not be a problem if there were pointers or auto-repeaters on the map to the layer, and not to the layer itself.)

Now this will not happen if map :: iterator :: operator-> returned a value_type link, not a value_type. That is, if it returns an lvalue, not an rvalue. It seems strange that this is not so, but I have not worked my way through the standard.

You can get around this by doing

 pair<int,layer>& piltmp = *xs.begin(); return piltmp.first; 

(Not verified.)

-one
source

All Articles