c++ - 将 shared_ptr<StructA> 移动到 shared_ptr<variant<StructA, StructB>>

标签 c++ c++14 c++17

我试图避免为一组普通的旧数据结构使用相当复杂的继承链,但我需要将它们全部存储在一个 vector 中,并与调用者共享所有权。

Struct A {};
Struct B {};

using TInstruction = std::variant<A, B>;

struct holder {
  std::vector<std::shared_ptr<TInstruction>> items;
};

static holder h;

// Every individual TInstruction gets its own add function, for validation purposes
void add(std::shared_ptr<A> a) {
  // Somehow add this to h, while still sharing ownership with the caller
  // h.emplace_back(???)
}


int main() {
  holder h;

  auto a = std::make_unique<A>();
  auto b = std::make_unique<B>();

  add(a);
  // add(b) // not implemented
}
通过对原始想法进行以下更改,我取得了中等(但非常糟糕)的成功:
  • 在变体内部使用共享指针,即 using TInstruction = std::variant<std::shared_ptr<A>, std::shared_ptr<B>>
  • add() 中接受 std::weak_ptr并使用 .lock()把它变成一个 std::shared_ptr

  • 我不介意#2(在我看来这可能是正确的方法),但是将 shared_ptr 保留在它的“外部”内部的变体中会导致一些非常冗长的代码和模式匹配。
    有可能做到这一点吗?我本质上想改变共享指针的类型,但仍然表达共享所有权的想法。

    最佳答案

    而不是使用 variant ,您可以利用 shared_ptr<void>能够持有shared_ptr任何东西,只要您自己跟踪它所持有的类型,例如:

    // Generic typelist
    template <typename...>
    struct Types;
    
    // Find the 0-based index of type T in Types<...>
    template <typename, typename>
    struct Index;
    
    // T is the first type in Types<...>
    template <typename T, typename... Us> 
    struct Index<T, Types<T, Us...>> : std::integral_constant<int, 0> {}; 
    
    // T is not the first type in Types<...>
    template <typename T, typename U, typename... Us> 
    struct Index<T, Types<U, Us...>>
        : std::integral_constant<int, 1 + Index<T, Types<Us...>>()> {}; 
    
    template <typename... Ts> 
    struct SharedPtrVariant {
        template <typename T>
        explicit SharedPtrVariant(std::shared_ptr<T> p)
            : sp(std::move(p)), index(Index<T, Types<Ts...>>()) {}
    
        template <typename T>
        std::shared_ptr<T> get() const {
            return std::static_pointer_cast<T>(
                Index<T, Types<Ts...>>() == index ? sp : nullptr);
        }   
    
       private:
        std::shared_ptr<void> sp; 
        int index;
    };
    

    关于c++ - 将 shared_ptr<StructA> 移动到 shared_ptr<variant<StructA, StructB>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62879275/

    相关文章:

    c++ - 平凡可移动但不可平凡复制

    c++ - 在 Visual Studio C++ 中弃用单个构造函数的正确语法是什么?

    c++ - 注释中的三字母,在 c++11 中转换,在 c++17 中忽略

    c++ - 将修改后的矩阵中的所有数字相加

    C++字符串如何

    c++ - 为什么Dev C++编译后PE文件中多了这么多节?

    c++ - 为什么 `std::array::at()` 没有实现为模板函数?

    c++ - 如何将 std::is_convertible_v 应用于一组可变参数?

    c++ - 使用包扩展的 Lambda 继承

    c++ - 如何判断cudaErrorIllegalAddress是由于目标地址还是源地址?