#include <complex>
struct S
{
static std::complex<double> constexpr c;
};
イニシャライザがないため、gccはエラーを生成します。 ClangとMSVCはエラーを生成しません。
私の知る限り、constexpr静的データメンバーは、引数なしで呼び出すことができるコンストラクターを持つクラスタイプであっても(この場合のように)、初期化子を持っている必要があります。残念ながら、私は自分の仮定を裏付ける最新のC++標準を持っていません。
したがって、正しいコードはコンストラクターで初期化する必要があります。たとえば、次のようになります。
struct S
{
static std::complex<double> constexpr c {};
};
どのコンパイラが正しいか、どれが間違っているかを誰かが証明できますか?
GCCは間違っています。
GCCは、constexpr
変数にC++ 14ルールを使用します。これには、初期化子を指定する必要があります。これは P0386 ごとに変更されます(太字のテキストは新しく追加されたテキストです):
9.2.3.2p3で、変更:
不揮発性n on-inlineconst静的データメンバーが整数型または列挙型である場合、クラス定義での宣言でabを指定できますrace-or-equal-initializerここで、すべての(= /// =)initializer-clauseは割り当て式は定数式(5.20)です。
リテラル型の静的データメンバーは、constexpr指定子を使用してクラス定義で宣言できます。その場合、その宣言は、代入式であるすべての初期化子句が定数式である中括弧または等しい初期化子を指定するものとします。 [注:どちらの場合も、メンバーは定数式で表示される場合があります。 —エンドノート]メンバーがプログラムでodr-used(3.2)であり、名前空間スコープ定義にイニシャライザーが含まれていない場合でも、メンバーは名前空間スコープで定義されます。インライン静的データメンバークラス定義で定義でき、b race-or-equal-initializerを指定できます。メンバーがconstexpr指定子で宣言されている場合、名前空間で再宣言できます。初期化子のないスコープ(この使用法は非推奨です。DXを参照してください)。他の静的データメンバーの宣言では、b race-or-equal-initializerを指定してはなりません。
この特定のケースには、2つの答えがあります。
以前のケース:ドラフト中 N3797 (C++14)、9.4.2.3(静的データメンバー)[class.static.data](強調鉱山):
リテラル型の
static
データメンバーは、constexpr
指定子を使用してクラス定義で宣言できます。もしそうなら、その宣言はbrace-or-equal-initializerを指定するものとします。initializer-clauseつまりAssignment-expressionは定数式です。
参照: http://en.cppreference.com/w/cpp/language/static#Constant_static_members 。
「この場合特定のの場合」と言ったのは、std::complex
double
に特化しています これはLiteralType
です。したがって、上記のルールが適用されます。一般的な(つまり、非リテラル)タイプについては、 codekaizers answer を参照してください。
後者の場合:C++の場合17、 xskxzrの答え を参照してください。
から dcl.constexpr#1 :
static
指定子で宣言された関数またはconstexpr
データメンバーは、暗黙的にinline
関数または変数です。
constexpr
static
データメンバーは暗黙的にinline
です。
また、 class#static.data- 、emphasismineから:
inline
static
データメンバーはclass
定義で定義でき、mayは_brace-or-equal-initializer
_。
したがって、GCCは間違っています。 _brace-or-equal-initializer
_はnot厳密に必要です。
参照: N4659 C++ 17ドラフト