1

I got a structure and a function like the following:

struct MYOVERLAPPED : public OVERLAPPED
{
    //...
};


void func1(std::unique_ptr<MYOVERLAPPED> pBuf)
{
    //...
};

I am obtaining a pointer to MYOVERLAPPED which i want to pass to the func1-function. The problem i encounter is, that no matter what i try i get the following errors :

What i did try already are the following: Try1:

std::unique_ptr<OVERLAPPED> pOver(//....)
HandleAcceptIndication(std::move(pOver));

Error: Error 1 error C2440: 'initializing' : cannot convert from '_OVERLAPPED **' to 'MYOVERLAPPED *'

Try2:

HandleAcceptIndication(new ACCEPT_OVERLAPPED);

Error 1 error C2664: 'HandleAcceptIndication' : cannot convert parameter 1 from 'MYOVERLAPPED *' to 'std::unique_ptr<_Ty>'

Anyone knows how i can pass this casted pointer of OVERLAPPED to MYOVERLAPPED to the function and why Try2 does not work either since i casually use std::unique_ptr<MYOVERLAPPED> pO(new MYOVERLAPPED) which does work...?

3 Answers 3

11

While you cannot convert from std::unique_ptr<base> to std::unique_ptr<derived> directly, it is not too hard to write a cast function that will be safe (i.e. not leak the resource under any circumstance, and only succeed if the cast is valid:

template <typename Dst, typename Src>
std::unique_ptr<Dst> unique_dynamic_cast( std::unique_ptr<Src>& ptr ) {
    Src * p = ptr.release();                             // [1]
    std::unique_ptr<Dst> r( dynamic_cast<Dst*>(p) );     // [2]
    if ( !r ) {
        ptr.reset( p );                                  // [3]
    }
    return r;                                            // [4]
}

The basic idea is that we need to extract the pointer from the std::unique_ptr and set it aside in [1]. We cannot try dynamic_cast directly, as if that fails, ptr would have released ownership, and the memory would be leaked. Then we try and perform the dynamic_cast [2] from the local pointer to the requested type of pointer and pass ownership onto the r result unique pointer. If the dynamic_cast fails, then r will be null, and we need to return ownership of the memory to the original std::unique_ptr [3], for calling code to decide what to do with it. We then return the converted std::unique_ptr to the caller in [4].

Sign up to request clarification or add additional context in comments.

6 Comments

wouldnt it be possible do directly dynamic_cast on unique_ptr.get() instead of release?
@Incubbus: Yes, that is also possible, but you have to make sure that only one std::unique_ptr holds ownership of the memory (i.e. if the dynamic_cast succeeds, the next thing would be releasing the memory from the original std::unique_ptr: std::unique_ptr<Dst> r( dynamic_cast<Dst*>(ptr.get()) ); if ( r ) ptr.release();
but it gives the same error... I asked this question, because i already tried this out... that freaks me out a bit :(... i dont have private inheritance or something like it within the structure so i dont know whats wrong :/
well... to be exactly it says: Error 1 error C2681: '_OVERLAPPED *' : invalid expression type for dynamic_cast for std::unique_ptr<ACCEPT_OVERLAPPED> ptr(dynamic_cast<ACCEPT_OVERLAPPED*>(pOverlapped.get()));
works fine with static cast... cannot use dynamic_cast, because OVERLAPPED has no virtual funcions (as the error description that came up today after i found some bugs, said)...
|
2

This doesn't work because you're trying to cast the wrong way in the inheritance hierarchy. You're trying to convert from Base* to Derived* implicitly.

Comments

0

unique_ptr<A> and unique_ptr<B> are unrelated types. You can't convert between them unless an implicit conversion exists between A* and B* (thanks UncleBens), which is not true in this case. Also you should not cast down the inheritance hierarchy with an instance that is not the subclass you are casting to. In this case, you're trying to cast a OVERLAPPED to a MYOVERLAPPED which is an invalid cast because an OVERLAPPED is not a MYOVERLAPPED. That's why you can't convert between the unique_ptr types in the first place.

If you are just trying to pass a unique_ptr to func1, you can do it like this:

func1(shared_ptr<MYOVERLAPPED>(new MYOVERLAPPED));

Also, by passing a unique_ptr to a function, the pointer in the original one gets set to NULL. Consider using references or shared_ptrs if you are not creating the unique_ptr as a temporary and passing it to the function and you need to use the same instance later.

4 Comments

Actually implicit conversion between unique_ptr<A> and unique_ptr<B> exists if there is an implicit conversion between A* and B*.
@Uncle ugh, I thought I went through this and couldn't do it. I'll revise my answer...
But i have to do something like this, because i am checking some variable and casting from OVERLAPPED to MYOVERLAPPED1 or MYOVERLAPPED2 depending on what the indicator says. (what i did before was (MYOVERLAPPED*)pOverlapped - which worked just fine, because pOverlapped points to an MYOVERLAPPED [yes, i know it can only "see" the overlapped part]) so how would you do this? or shall i switch back to native pointers - which isn´t that comfortable
@Incubbus assuming OVERLAPPED destructor is virtual and you have a pointer named overlappedPtr of type OVERLAPPED* that really points to a MYOVERLAPPED1, you can do func1(unique_ptr<MYOVERLAPPED1>((MYOVERLAPPED1*)overlappedPtr);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.