通过成员地址激活嵌套工会合法吗

Is it legal to activate nested unions via the address of their members?

本文关键字:嵌套 成员 地址 激活      更新时间:2023-10-16

以下代码合法吗(在c++11/14中)?

bool foo() {
  union bar { int i; bool b; };
  union baz { char c; bar b; };
  auto b = baz{'x'};
  auto barptr = &b.b;
  auto boolptr = &barptr->b;
  new (boolptr) bool{true};
  return b.b.b;
}

这个例子很傻,但我正在讨论一个可变的variant实现,该实现使用嵌套的并集而不是用于可变成员的char []块,允许这样做将使我当前在复制构造函数方面的尝试更加干净。

将其分解为两个子问题:

  1. 即使b.b处于非活动状态,通过访问barptr的成员来分配boolptr是否合法
  2. boolptr的原位构建是否激活b.bb.b.b

请参考本标准。

关于并集和类型双关的许多问题都不清楚您的程序是否定义了行为,尽管我强烈希望它在任何正常的实现中都能像预期的那样运行。我可以肯定地说,这个程序:

#include <memory>
#include <new>
template <typename T>
inline void destruct(T& t) { t.~T(); }
template <typename T, typename...Args>
inline void construct(T& t, Args&&...args) {
  ::new((void*)std::addressof(t)) T(std::forward<Args>(args)...);
}
template <typename T>
inline void default_construct(T& t) {
  ::new((void*)std::addressof(t)) T;
}
bool foo() {
  union bar { int i; bool b; };
  union baz { char c; bar b; };
  auto b = baz{'x'};
  destruct(b.c);
  default_construct(b.b);
  construct(b.b.b, true);
  return b.b.b;
}

符合标准,具有您想要的效果,并且在现代编译器中编译为与原始程序完全相同的程序集。原件:

foo():
    movl    $1, %eax
    ret

保证合规:

foo():
    movl    $1, %eax
    ret