gpt4 book ai didi

c++ - C++ 标准是否允许复制任意多态数据结构?

转载 作者:行者123 更新时间:2023-11-30 04:48:28 24 4
gpt4 key购买 nike

我搜索了 StackOverflow,但找不到直接解决此问题的问题。

首先是一些上下文:我正在尝试实现一个 Either输入可以处理多态数据的 C++,就像你可以抛出一个 std::runtime_error没有 new -关键词。一切都适用于原始类型、POD 和引用,但鉴于我们无法预先知道多态数据结构的大小,事情变得更加困难。然后我考虑将结构复制到堆上的原始缓冲区,以便我可以将它传递过来,就好像它在堆栈上一样。

Either<L, R> 的示例-类型:

Either<std::runtime_error, int> doSomeStuff() {
if (err) {
return left(std::runtime_error("Not right!"));
}
return right(42);
}

我尝试了类似 std::memcpy(buf, reinterpret_cast<char*>(static_cast<T*>(&value)), sizeof(T)) 的东西,但我不断收到 SIGSEGV 错误。这是因为,正如我怀疑的那样,多态结构持有额外的簿记,在复制时会损坏?有没有办法保持任意多态结构T在堆上,这样我就可以像传递普通的堆栈分配对象一样传递它?或者在今天的 C++ 标准中这样的东西是“未定义的”吗?

更新:这是我目前拥有的代码。它不是很漂亮,但它是我所拥有的最好的。

struct ConstBoxRefTag { };
struct BoxMoveTag { };
struct PlainValueTag { };
// struct BoxValueTag { };

template<typename T>
struct GetTag { using type = PlainValueTag; };

template<typename T>
struct GetTag<const Box<T>&> { using type = ConstBoxRefTag; };

template<typename T>
struct GetTag<Box<T>&&> { using type = BoxMoveTag; };

template<typename T>
struct GetTag<Box<T>> { using type = ConstBoxRefTag; };


template<typename T>
class Box<T, typename std::enable_if<std::is_polymorphic<T>::value>::type> {

void* buf;
size_t sz;

template<typename R, typename Enabler>
friend class Box;

public:

using Type = T;

template<typename R>
Box(R val): Box(typename box::GetTag<R>::type {}, val) {}

template<typename R>
Box(ConstBoxRefTag, R oth): buf(std::malloc(oth.sz)), sz(oth.sz) {
std::memcpy(buf, oth.buf, oth.sz);
}

template<typename R>
Box(BoxMoveTag, R oth): buf(std::move(oth.buf)), sz(std::move(oth.sz)) {
oth.buf = nullptr;
};

template<typename R>
Box(PlainValueTag, R val): buf(std::malloc(sizeof(R))), sz(sizeof(R)) {
std::memcpy(buf, reinterpret_cast<void*>(static_cast<T*>(&val)), sizeof(R));
}

template<typename R>
R as() const {
static_assert(std::is_base_of<T, R>::value, "Class is not a subtype of base class");
return *static_cast<const R*>(reinterpret_cast<const T*>(&buf));
}

T& reference() {
return *reinterpret_cast<T*>(&buf);
}

const T& reference() const {
return *static_cast<T*>(&buf);
}

~Box() {
if (buf != nullptr) {
reference().~T();
std::free(buf);
}
}

};

最佳答案

事实上,该标准最近添加了一个概念“平凡可复制”,例如在不可平凡复制的对象上使用 memcpy 不会生成有效对象。在引入“平凡可复制”之前,这是由 POD-ness 控制的。

要复制 C++ 对象,您需要调用其复制构造函数。没有标准的多态方法可以做到这一点,但一些类层次结构选择包含满足您需要的虚拟 clone() 函数(或类似函数)。

您的另一个选择是找到完全避免复制的方法。

关于c++ - C++ 标准是否允许复制任意多态数据结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55774630/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com