簡體   English   中英

std::shared_ptr 怎么可能<derived>轉換為 std::shared_ptr<base> 沒有編譯器錯誤?</derived>

[英]How is it possible that std::shared_ptr<Derived> casts to std::shared_ptr<Base> with no compiler errors?

我正在嘗試實現自定義智能指針。 所以我有這樣的事情:

// Base class for every object
class Base {
public:
    int n_holders {};
};

class Derived : public Base {};

// Custom shared pointer
template<class T>
class Sptr {
public:
    T* obj;
    Sptr(T* obj_) : obj{obj_} {}
};

void SomeFunc(Sptr<Base> obj) {}

void SomeFunc2(std::shared_ptr<Base> obj) {}

int main()
{
    auto a = Sptr<Base>(new Base());
    SomeFunc(a); // OK

    auto b = Sptr<Derived>(new Derived());
    SomeFunc(b); // Error. No matching function call to SomeFunc

    auto c = std::shared_ptr<Base>(new Base());
    SomeFunc2(c); // OK

    auto d = std::shared_ptr<Derived>(new Derived());
    SomeFunc2(d); // OK !!!
}

我的問題是,如果使用std::shared_ptr沒有錯誤,為什么編譯器不能自動從Sptr<Derived>轉換為Sptr<Base> 如何使它成為可能?

std::shared_ptr有一個構造函數(來自cppreference ):

template< class Y >
shared_ptr( const shared_ptr<Y>& r ) noexcept;  (9)     

這個超載...

構造一個 shared_ptr,它共享由 r 管理的 object 的所有權。 如果 r 沒有管理 object,這也管理沒有 object。 如果 Y 不能隱式轉換為(C++17 前)與(C++17 起)T* 兼容,則模板重載不參與重載決議

因此,在某種意義上,棘手的部分不是轉換共享指針,而是在指針類型不可隱式轉換時阻止它。 您可以使用 SFINAE 來實現這一點。

這是一個玩具示例,僅當T1T2繼承時才啟用從Bar<T1>Bar<T2>的轉換(但不是相反):

#include <type_traits>

template <typename T1>
struct Bar {
    Bar() {}

    template <typename T2, typename std::enable_if_t<std::is_base_of_v<T1,T2>,int> = 0>
    Bar(Bar<T2>){} 

};

struct Foo {};
struct Derived : Foo {};

int main(){
    Bar<Derived> d;
    Bar<Foo> b;
    //d = b; // eror
    b = d;  // OK
}

現場演示

您可能希望它更通用,例如共享指針,以便在T2*可以轉換為T1*時允許這種轉換,而不僅僅是當它們相互繼承時(參見std::is_convertible ,我不得不承認,我沒有t 真正理解 C++17 帶來的變化,所以我只能猜測:在這種情況下,可能是它的std::is_layout_compatible )。 因此,要模仿 C++17 之前的智能指針,您可以使用:

    template <typename T2, typename std::enable_if_t<std::is_convertible_v<T2*,T1*>,int> = 0>
    Bar(Bar<T2>){} 

這可以轉換所有T2 ,其中T2*可以轉換為T1*

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM