I am a relative C ++ newbie trying to convert an existing project from raw pointers with convolutional memory management protocol using C ++ 11 shared_ptr . In general, this happens very smoothly, and I think I understand how shared_ptr works in terms of the semantics of movement, links to links, etc. Good material.
However, I got into a strange error that I do not understand and do not know how to fix. First, a little background. I have a class hierarchy based on an abstract base class called EidosValue , and a class called EidosValue_Int_vector (indirectly) is a concrete subclass of this:
class EidosValue class EidosValue_Int : public EidosValue class EidosValue_Int_vector : public EidosValue_Int
My code usually loads in EidosValue , but sometimes, especially when creating a new value, I need to process a specific subclass.
I made typedefs for shared_ptr for these classes, so I have:
typedef std::shared_ptr<EidosValue> EidosValue_SP; typedef std::shared_ptr<EidosValue_Int_vector> EidosValue_Int_vector_SP;
among others. Ok, so now the core of the problem. I have a function that returns the created EidosValue_SP . Depending on the logic inside the function, it can create one of several specific subclasses of EidosValue . So I am doing something like this:
EidosValue_SP MyClass::MyMethod(...) { EidosValue_SP result; if (...) { EidosValue_Int_vector_SP int_result_SP = make_shared<EidosValue_Int_vector>(); ... do subclass-specific stuff with int_result_SP... result.swap(int_result_SP); } else (...) { ...similar logic for other subclasses... } ...other shared logic... return result; }
The problem is calling swap() . I get the error message: " Non-const lvalue reference to type 'shared_ptr<EidosValue>' cannot bind to a value of unrelated type 'shared_ptr<EidosValue_Int_vector>' ". This is bewildering, since EidosValue_Int_vector not a "disconnected type", it is a public subclass of EidosValue, and the code here knows it. If I type result = make_shared<EidosValue_Int_vector>(); , the compiler has no problems with this, so it clearly knows that types are related and compatible. For some reason this is just not like in the context of swap() . Elsewhere in my project, I was able to simply do return int_result_SP; with the declared return type EidosValue_SP, and it worked fine - the compiler would happily consider EidosValue_Int_vector_SP as EidosValue_SP in this context, but I cannot do this because of the common logic at the bottom of the function.
In my implementation, I am a bit limited because this code is a bottleneck and should work quickly (and yes, I know that from the actual toolkit of the code and yes, it really matters). Therefore, it is very important to use make_shared to avoid double distribution, and I also highly recommend avoiding increment / decrement of int_result_SP when I pass a pointer from int_result_SP to the result; I do not want you to have a point in time when there are two shared_ptrs pointing to a new instance. So swap() seems the obvious way; but I am blocked by this compiler error. Why is this happening and how can I fix it? Thanks!
ADDITION:
Oh, thinking about it further, I'm sure I know why the error occurs. swap() has no objection to placing EidosValue_Int_vector in EidosValue_SP , but has a problem with putting EidosValue in EidosValue_Int_vector_SP ; types are incompatible in this direction. I did not think about it this way, since result does not matter (i.e. Has nullptr , I think) in it; but of course swap() does not know this. OK, so if this is a problem, the question remains: how can I make the transfer, saving the code quickly - without making refcount inc / dec and without moving away from using make_shared ? Now that I understand the problem (I think), it seems likely that there is only some kind of API or trick that I missed ...