静态数据成员:“ const声明/ constexpr定义”是否起作用?

时间:2019-12-19 05:37:01

标签: c++ language-lawyer constexpr static-data

以下代码尝试提供constexpr 类型X的静态数据成员,它属于类型X本身。 在标准库(C ++ 20)中,似乎有这样的示例 与(至少)类“ std :: strong_ordering”及其少量静态 constexpr成员分别命名为“等于”,“较少”,“更大”和“等效”。 我想知道如果没有编译器魔术,是否可以(以及如何)实现这一点。

直接声明(包括定义)可以 似乎不能与任何编译器一起使用,也不是有效的C ++。 话虽这么说,后来声明为“ const” (在类外部)的定义为“ constexpr” 可以在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定义”的窍门。 Can't a class have static constexpr member instances of itself?

  2. 这其中提到了“ const声明/ constexpr定义”技巧,但 没有明确回答是否有效的C ++代码的问题。 Static const declaration, constexpr definition of variable, valid c++?

0 个答案:

没有答案