我试图避免为一组普通的旧数据结构使用相当复杂的继承链,但我需要将它们全部存储在一个 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/