简体   繁体   English

C++ 构建错误 — unique_ptr 到 shared_ptr

[英]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.我在构建过程中遇到了一个奇怪的问题,我有一些 C++ 代码用于使用 JNI 包装器的 Android 项目中。 In the C++ code, I have a class T and an interface T_Interface.在 C++ 代码中,我有一个 class T 和一个接口 T_Interface。 T extends from T_Interface. T 从 T_Interface 扩展。

I am trying to call a method which expects std::shared_ptr<T_Interface> as a parameter.我正在尝试调用一个期望std::shared_ptr<T_Interface>作为参数的方法。 My code has std::unique_ptr<T> t and I call the method with parameter std::move(t)我的代码有std::unique_ptr<T> t我用参数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:您正在尝试使用以下std::shared_ptr构造函数:

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> !您不是从std::unique_ptr<T>创建std::shared_ptr<T> T> ! You're trying to create a std::shared_ptr<T_Interface> from std::unique_ptr<T> .您正在尝试从std::unique_ptr<T>创建一个std::shared_ptr<T_Interface> > 。 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).这应该也可以,只要您将语言标准设置得足够高(例如 gcc 只接受--std=c++14或更高版本,MSVC 2017 不需要特殊参数)。

#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.但这适用于最近在 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).提供用于调用编译器的确切命令行(例如,将-DVERBOSE_MAKEFILE=YES传递给 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 ;你真的不应该能够自动将unique_ptr转换为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.尝试使用std::shared_ptr(t.release())std::shared_ptr(std::move(t))代替:显式转换告诉读者您实际上在做什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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