gpt4 book ai didi

c++ - C++14 标准布局类型可以将 `alignas` 用于字段吗?

转载 作者:太空狗 更新时间:2023-10-29 23:13:21 27 4
gpt4 key购买 nike

我想使用模板来简化具有非平凡类型的 union 的构造。以下内容在实践中似乎“有效”,但在技术上不符合规范:

template<typename T> struct union_entry {
void (*destructor_)(void *); // how to destroy type T when active
T value_;
};
union U {
union_entry<A> a;
union_entry<B> b;
// ... some constructor and destructor...
};

问题是(根据 N4141)只有当两个结构都是标准布局类型时,您才能访问 union 中两个结构的公共(public)初始序列(即 destructor_ 字段)——至少根据9.5.1 中的非规范性注释。根据 9.0.7,标准布局类型不能有任何非标准布局的非静态数据成员。因此,如果 A 或 B 不是标准布局,则访问 destructor_ 将变得非法。在错误的 union 中。

一个漏洞似乎是制造union_entry转动标准布局value_进入 alignas(T) char[sizeof(T)] . 9.0.7 似乎没有排除使用 alignas 的可能性。 .因此,我的问题是:以下是任何类型的标准布局类型 T ? 因此可以 value_转换到T&模拟前面的例子,同时仍然允许 destructor_用于非事件 union_entry

template<typename T> struct union_entry {
void (*destructor_)(void *);
alignas(T) char value_[sizeof(T)];
}

在 clang-3.8.1 和 g++-6.2.1 中,std::is_standard_layout建议 union_entry<T>即使 T 也是标准布局不是。这是我想如何使用此技术的完整工作示例:

#include <cassert>
#include <iostream>
#include <new>
#include <string>

using namespace std;

template<typename T> struct union_entry {
void (*destructor_)(void *);
alignas(T) char value_[sizeof(T)];

union_entry() : destructor_(nullptr) {}
~union_entry() {} // Just to cause error in unions w/o destructors

void select() {
if (destructor_)
destructor_(this);
destructor_ = destroy_helper;
new (static_cast<void *>(value_)) T{};
}
T &get() {
assert(destructor_ == destroy_helper);
return *reinterpret_cast<T *>(value_);
}

private:
static void destroy_helper(void *_p) {
union_entry *p = static_cast<union_entry *>(_p);
p->get().~T();
p->destructor_ = nullptr;
}
};

union U {
union_entry<int> i;
union_entry<string> s;
U() : i() {}
~U() { if (i.destructor_) i.destructor_(this); }
};

int
main()
{
U u;
u.i.select();
u.i.get() = 5;
cout << u.i.get() << endl;
u.s.select();
u.s.get() = "hello";
cout << u.s.get() << endl;
// Notice that the string in u.s is destroyed by calling
// u.i.destructor_, not u.s.destructor_
}

最佳答案

感谢@Arvid,他向我指出了std::aligned_storage ,我相信在标准的第 20.10.7.6 节中有一个明确的(尽管是非规范的)答案(我认为与 N4141 相同)。

首先,表 57 表示 aligned_storage "成员 typedef type应为 POD 类型...”,其中 9.0.10 明确指出“POD 结构是一个非 union 类,它既是普通类又是标准布局类 。”

接下来20.10.7.6.1给出了一个不规范的示例实现:

template <std::size_t Len, std::size_t Alignment>
struct aligned_storage {
typedef struct {
alignas(Alignment) unsigned char __data[Len];
} type;
};

那么清楚alignas的用途不会阻止类型成为标准布局。

关于c++ - C++14 标准布局类型可以将 `alignas` 用于字段吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39991121/

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