可以同时包含 Foo* 和 std::shared_ptr<Foo> 的类型

Vla*_*hev 6 c++ c++17

能够以相同类型存储 std::shared_ptr 或 Foo* 的最方便的方法是什么?

Foo* a = ...;
std::shared_ptr<Foo> b = ...;

Bar c = a; // Success, Bar type can hold Foo*
Bar d = b; // Success, Bar type can also hold std::shared_ptr<Foo>
Run Code Online (Sandbox Code Playgroud)

std::variant<Foo*, std::shared_ptr< Foo>> 没问题,但不可能直接取消引用它,这有点烦人。有没有更好的办法?

Ded*_*tor 7

只需使用一个std::shared_ptr<Foo>.

虽然它很少有用,但实际上您可以构造一个非拥有非计数std::shared_ptr

auto p = std::shared_ptr<Foo>{std::shared_ptr<void>(), raw_pointer};
Run Code Online (Sandbox Code Playgroud)

如果你想迎合不尊重抽象的怪人(具体来说,看看引用计数),你也可以在某处藏一个永恒的锚并使用它:

struct pass_t {
    template <class... T>
    constexpr int operator()(T&&...) noexcept
    { return 0; }
};
constexpr inline pass_t pass;

inline const std::shared_ptr<void> anchor {nullptr, pass};

auto p = std::shared_ptr<Foo>{anchor, raw_pointer};
Run Code Online (Sandbox Code Playgroud)


Cal*_*eth 3

您可以只包装std::variant<Foo*, std::shared_ptr< Foo>>一些可以进行正确解引用的内容

class Bar
{
public:
    explicit Bar(Foo* foo) : foo(foo) {}
    explicit Bar(std::shared_ptr<Foo> foo) : foo(foo) {}

    Foo& operator*() const { return std::visit(deref, foo); }
    Foo* operator->() const { return std::visit(arrow, foo); }

private:
    struct {
        Foo& operator()(Foo* f) { return *f; }
        Foo& operator()(std::shared_ptr<Foo> f) { return *f; }
    } deref;

    struct {
        Foo* operator()(Foo* f) { return f; }
        Foo* operator()(std::shared_ptr<Foo> f) { return f.get(); }
    } arrow;

    std::variant<Foo*, std::shared_ptr<Foo>> foo;
};
Run Code Online (Sandbox Code Playgroud)