【发布时间】:2020-07-13 15:34:34
【问题描述】:
我试图避免一组普通旧数据结构的相当复杂的继承链,但我需要将它们全部存储在一个向量中 + 与调用者共享所有权。
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 保留在变体的“外部”内部会导致一些非常冗长的代码和模式匹配.
有可能做到这一点吗?我本质上是想改变共享指针的类型,但仍然表达共享所有权的想法。
【问题讨论】:
-
也许您可以使用“别名构造函数”(cppreference 上的#8)。尽管它给出的示例与您想要的相反。如果您已经有一个指向变体的共享指针并且想要创建一个指向具有相同所有权的内部对象的共享指针,那么使用它会很简单。但反过来可能就不行了。
-
实际上,您打算如何将对象放入变体中?变体要么拥有它自己的副本,要么将对象移入其中。无论哪种情况,为什么它仍然需要与调用者共享所有权?如果您真的想在变体中拥有相同的对象,那么在我看来选项 1 是您唯一的选择。
-
共享指针的变体绝对是解决此问题的“正确”方式。它是冗长的怎么办?可能有办法减少这种情况。
-
@Kevin & @HTNW 谢谢你,看起来这个问题有点傻,我明白为什么会这样:) API 打算让用户只用一堆说
.add(<reference_to_shared_ptr>)不同的类型,使零件或多或少地得到解决。我必须在代码的几个部分中对这些类型进行“模式匹配”,这是每次拼出variant.get<shared_ptr<StructType>>(var)变得相当冗长的地方。但我会接受这个打击。我知道这个问题很奇怪,但我不是专家,所以我想在这里联系:)