Question

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...?

Was it helpful?

Solution

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].

OTHER TIPS

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top