简体   繁体   中英

C++ build error — unique_ptr to shared_ptr

I am facing a weird issue during build, I have some C++ code which is used in an Android project using JNI wrapper. In the C++ code, I have a class T and an interface T_Interface. T extends from T_Interface.

I am trying to call a method which expects std::shared_ptr<T_Interface> as a parameter. My code has std::unique_ptr<T> t and I call the method with parameter std::move(t)

I am seeing the below error:

no viable conversion from '
remove_reference<unique_ptr<T, default_delete<T> > &>::type'
(aka 'std::__ndk1::unique_ptr<T, std::__ndk1::default_delete<T> >')
to 'std::shared_ptr<T_Interface>' T extends from T_Interface type

Code Sample:

std::unique_ptr<T> t = A::B::T::create(config);

std::shared_ptr<C::D::X> test =
        XYZ::create(
            config, customerDataManager, std::move(t), userInterfaceManager, nullptr, deviceInfo);

Error comes in std::move(t) parameter.

std::unique_ptr<PQR> XYZ::create(
    const P& configuration,
    std::shared_ptr<Blah> customerDataManager,
    std::shared_ptr<T_Interface> storage,
    std::shared_ptr<Blah> authRequester,
    std::shared_ptr<Blah> httpPost,
    std::shared_ptr<Blah> deviceInfo) {
}

You're attempting to use the following std::shared_ptr constructor:

template< class Y, class Deleter > shared_ptr( std::unique_ptr<Y,Deleter>&& r );

And indeed, it works:

#include <memory>

struct Wrapper {
    Wrapper(const std::shared_ptr<int> &v) : value(v) {}
    std::shared_ptr<int> value;
};

std::unique_ptr<Wrapper> create(const std::shared_ptr<int> &ptr)
{
    return std::make_unique<Wrapper>(ptr);
}

int main()
{
    std::unique_ptr<int> value = std::make_unique<int>(10);
    std::unique_ptr<Wrapper> wrapped = create(std::move(value));
}

But what you're using is slightly different: you're trying to do two things at once. You're not creating a std::shared_ptr<T> from std::unique_ptr<T> ! You're trying to create a std::shared_ptr<T_Interface> from std::unique_ptr<T> . This should work as well, as long as you set the language standard high enough (eg gcc only accepts it with --std=c++14 or higher, MSVC 2017 needs no special arguments).

#include <memory>

struct I_Wrapper {};

struct Wrapper : I_Wrapper {
    Wrapper(const std::shared_ptr<int> &v) : value(v) {}
    std::shared_ptr<int> value;
};

struct WrapperWrapper {
    WrapperWrapper(const std::shared_ptr<I_Wrapper> &w) : value(w) {}
    std::shared_ptr<I_Wrapper> value;
};

auto create1(const std::shared_ptr<int> &ptr)
{
    return std::make_unique<Wrapper>(ptr);
}

auto create2(const std::shared_ptr<I_Wrapper> &ptr)
{
    return std::make_unique<WrapperWrapper>(ptr);
}

int main()
{
    std::unique_ptr<int> value = std::make_unique<int>(10);
    std::unique_ptr<Wrapper> wrapped = create1(std::move(value));
    std::unique_ptr<WrapperWrapper> wrappedWrapped = create2(
        std::move(wrapped)
    );
}

So maybe you're using a very old compiler. But this works just fine with anything reasonably recent on godbolt. You're probably not telling us something. At minimum you'd need to:

  1. Create an actual minimal example that is meant to compile and has dummy methods and types that match the signatures of the types you use.

  2. Double check that the example doesn't compile, and the compilation fails with the same error.

  3. Provide the exact command line used to invoke the compiler (eg pass -DVERBOSE_MAKEFILE=YES to cmake).

  4. Provide the exact version of the compiler, and the platform it runs on.

That is to be expected. You really shouldn't be able to automatically convert unique_ptr to shared_ptr ; the ownership models are sufficiently different that that conversion will be the wrong choice more often than not.

Try using std::shared_ptr(t.release()) or std::shared_ptr(std::move(t)) instead: the explicit conversion tells the reader what you're actually doing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM