1

以下代码尝试提供属于 X 类型本身的 X 类型的 constexpr 静态数据成员。在标准库(C++20)中,似乎有这样的例子,(至少)类“std::strong_ordering”和它的少数静态constexpr成员命名为“equal”、“less”、“greater”和“相等的'。我想知道是否(以及如何)在没有编译器魔法的情况下实现这一点。

直接声明(包括定义)似乎不适用于任何编译器,也不是有效的 C++。话虽如此,随后(在类之外)定义为“constexpr”的声明为“const”似乎适用于 GCC,至少在某些情况下适用于 Clang。

我的问题如下:

  1. 由“const 声明”和“constexpr 定义”组成的技巧是否形成了有效的 C++ 代码,该代码实际上在 X 类本身内部提供了 X 类型的有效静态 constexpr 数据成员?
  2. 非模板版本(类型 Foo)使用 GCC 和 Clang 编译,而模板版本(类型 Bar<0>)仅使用 GCC 编译。是否有任何规则可以使非模板版本有效的 C++ 代码和模板成为无效的 C++ 代码?
  3. Clang 产生的错误可以被认为是编译器错误吗?

源代码(C++17):

// With this non template struct,
// It compiles successfully with GCC and Clang.
struct Foo
{
  // A data member.
  int val;

  // A static data member.
  // It is declared here as 'const'
  // and defined below as 'constexpr'.
  static Foo const instance;

  // A constexpr constructor.
  constexpr Foo(int value) noexcept : val{ value } {}
};

// With this non template struct,
// It compiles successfully with GCC
// but it generates an error with Clang.
template<int N>
struct Bar
{
  // A data member.
  int val;

  // A static data member.
  // It is declared here as 'const'
  // and defined below as 'constexpr'.
  static Bar const instance;

  // A constexpr constructor.
  constexpr Bar(int value) noexcept : val{ value } {}
};

// Definition of the static
// data member of the struct Foo.
// Note that it is defined here as 'constexpr'
// while it was declared above only as 'const'.
constexpr Foo const Foo::instance{32};

// Definition of the static data
// member of the template struct Foo.
// Note that it is defined here as 'constexpr'
// while it was declared above only as 'const'.
template<int N>
constexpr Bar<N> const Bar<N>::instance{32};

// The main function.
int main()
{
  // Init a constexpr const reference to
  // the static data member object of type Foo.
  constexpr Foo const& foo{ Foo::instance };

  // Init a constexpr const reference to
  // the static data member object of type Bar<0>.
  constexpr Bar<0> const& bar{ Bar<0>::instance };

  // This compile time check
  // works fine with GCC and Clang.
  static_assert(foo.val == 32);

  // This compile time check works fine with GCC
  // but generates a compilation error with Clang.
  static_assert(bar.val == 32);

  // Return zero.
  return 0;
};

以前的 StackOverflow 相关问题:

我引用了两个相关的 StackOverflow 问题,但(在我看来)并没有明确回答我的问题。

  1. 这个试图实现与我相同的目标,但似乎没有提到“const 声明/ constexpr 定义”技巧。一个类不能有自己的静态 constexpr 成员实例吗?

  2. 这个提到了“const 声明/constexpr 定义”技巧,但没有明确回答它是否是有效的 C++ 代码的问题。静态 const 声明,变量的 constexpr 定义,有效的 C++?

4

0 回答 0