constexprコンストラクターで配列を初期化することは正当ですか?


11

次のコードは正当ですか?

template <int N>
class foo {
public:
    constexpr foo()
    {
        for (int i = 0; i < N; ++i) {
            v_[i] = i;
        }
    }

private:
    int v_[N];
};

constexpr foo<5> bar;

Clangはそれを受け入れますが、GCCとMSVCはそれを拒否します。

GCCのエラーは次のとおりです。

main.cpp:15:18: error: 'constexpr foo<N>::foo() [with int N = 5]' called in a constant expression
   15 | constexpr foo<5> bar;
      |                  ^~~
main.cpp:4:15: note: 'constexpr foo<N>::foo() [with int N = 5]' is not usable as a 'constexpr' function because:
    4 |     constexpr foo()
      |               ^~~
main.cpp:4:15: error: member 'foo<5>::v_' must be initialized by mem-initializer in 'constexpr' constructor
main.cpp:12:9: note: declared here
   12 |     int v_[N];
      |         ^~

この種のコードで問題がなければ、index_sequencesの使用をかなり減らすことができます。


1
Gcc10もそれを受け入れます。
songyuanyao

MSVCからのエラーを記録できますか?
max66

...そしてGCCも。
1

1
@songyuanyao-g ++ 10はC ++ 20をコンパイルしてそれを受け入れます。C ++ 17以前のコンパイルを拒否します。ポイントは、_vC ++ 17まで、初期化リストで初期化する必要があるようです。たぶんC ++ 20で何かが変更されています。
max66

2
それはクランが静的ストレージ期間オブジェクトは「言うことをゼロにされることをその「意識」を使用して提案することができるので、実際に面白い@Evgは大丈夫、このオブジェクトは、デフォルト・初期化されている可能性がありますが、そのから読み込むintメンバーは、未定義の動作を持っていることはありません」GCCがそれを実行していないのは準拠しているのか、それともその逆か...
オービットのライトネスレース

回答:


13

C ++ 20までconstexprコンテキストでは、単純なデフォルトの初期化は禁止されていました

その理由は、私が推測しているように、デフォルトで初期化されたプリミティブ、プログラムに未定義の動作を与える行為、および未定義の動作を伴う式は完全に禁止されているconstexprref)。ただし、言語は拡張されているため、コンパイラーはこのような読み取りが行われたかどうかを確認する必要があり、行われていない場合は、デフォルトの初期化を受け入れる必要があります。コンパイラーにとっては少し手間がかかりますが、(ご覧のとおり!)プログラマーにとっては大きなメリットがあります。

このホワイトペーパーでは、未定義の動作の呼び出しを禁止し続けながら、constexprコンテキスト内の自明なデフォルトの構成可能な型のデフォルトの初期化を許可することを提案しています。つまり、初期化されていない値が読み取られない限り、そのような状態はconstexprでヒープとスタックの両方に割り当てられたシナリオで許可されます。

C ++ 20以降、v_あなたのように「初期化されていない」ままにすることは合法です。次に、そのすべての要素の値を割り当てることに進みました。これは素晴らしいことです。


4
@ max66私も!私がしたことは、ウィキペディアのC ++ 20変更リストをスキャンして、に関連する何かを見つけconstexpr、リンクされた提案を
読み飛ばす

3
悪い点は、私がC ++を使用している20年以上です。毎日何か新しいことを学ぶなら...または私が悪いプログラマーであるか、C ++が複雑になりすぎています。
max66

5
@ max66ほぼ間違いなく後者です。また、2、3年ごとに根本​​的に変化し続けるという事実は、急速に変化するターゲットになります。誰がそれについていけますか?コンパイラでさえそれに追いついていません。
オービット

@ max66このペーパーが思い浮かびます:Vasaを覚えてください!
1

@Evgああ、すごい、その紙は(IRONY)を通り過ぎました。スポット!
オービット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.