未命名命名空间中的非静态匿名联合体。

9

gcc和msvc编译这段代码时出现了错误,错误信息为namespace-scope anonymous aggregates must be static。但是clang编译没有问题。 https://godbolt.org/z/WecT6vP91

namespace {
    union {
        int a;
        long b;
    };
}

https://en.cppreference.com/w/cpp/language/union中写道:

命名空间作用域的匿名联合必须声明为静态的,除非它们出现在未命名的命名空间中。

这似乎是gcc和msvc的一个bug?


编辑:

然而,Clang拒绝编译未在未命名命名空间中嵌套的命名命名空间中的非静态匿名联合。此规则是否可以更改为“...除非它们出现在直接或间接的未命名命名空间中”(这似乎有另外一个问题,请参见下文)或 “... 除非它们具有内部链接”?或者为什么不行?

namespace {
  namespace ns {
    union {
      int a;
      long b;
    };
  }
}

根据未命名命名空间内名称的外部链接,未命名命名空间中的名称可以具有C语言链接。即使Clang接受具有C语言链接的非静态匿名联合体,但实际上不会生成链接符号,这似乎毫无意义。它是否被标准允许?如果允许,那么在直接或间接未命名命名空间内使用extern "C"有什么效果?
namespace {
  extern "C" union {
    int a;
    long b;
  };
}

是的?已经问过并回答了。 - StoryTeller - Unslander Monica
1个回答

0
GCC和MSVC还没有完成实现P1787R6;以前,规则实际上要求使用static,而Cppreference是错误的(!)。

之前,规则实际上要求无论如何都必须使用 static。例如,C++17 规定:「在命名空间或全局命名空间中声明的匿名联合体必须声明为 static。」https://timsong-cpp.github.io/cppwp/n4659/class.union.anon#2 - Language Lawyer
@LanguageLawyer:我认为你说得对,我过于简化了,但是无名命名空间内的命名空间呢? - Davis Herring
@DavisHerring 我刚试了一下。即使是在未命名的命名空间内,非静态匿名联合体也无法通过Clang编译。看起来Clang只是“字面上”遵循标准。也许规则可以是“……除非它们出现在直接或间接的未命名命名空间中”(这似乎还有另一个问题,请参见编辑后的问题描述)或“……除非它们具有内部链接”? - VainMan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接