11

かなり基本的な何かが欠けているようです。コンパイル時に const 配列メンバーを使用しようとしています。

const int list[3] = { 2, 5, 7 };
const int a = list[2]; // this doesn't error?

template<int N1, int N2>
struct tmax {
  enum { value = ((N1 > N2) ? N1 : N2) };
};

const int b = tmax<2,4>::value;
const int c = tmax<list[0],list[1]>::value; // error is here

int main()
{
  return 0;
}

エラー:

prog.cpp:10:24: error: 'list' cannot appear in a constant-expression
prog.cpp:10:30: error: an array reference cannot appear in a constant-expression

ここに関連するIDEOneリンクがあります

では、なぜこれが機能しないのでしょうか。私は何が欠けていますか?どうすればいいですか?

4

2 に答える 2

9

オブジェクトが であるからとconstいって、それがコンパイル時の定数式であるとは限りません。

main.cpp:10:20: error: non-type template argument is not a constant expression
const int c = tmax<list[0],list[1]>::value; // error is here
                   ^~~~~~~
main.cpp:10:20: note: read of non-constexpr variable 'list' is not allowed in a constant expression
main.cpp:1:11: note: declared here
const int list[3] = { 2, 5, 7 };
          ^

これが次の理由ですconstexpr

constexpr int list[3] = { 2, 5, 7 };

template<int N1, int N2>
struct tmax {
    enum { value = ((N1 > N2) ? N1 : N2) };
};

const int b = tmax<2,4>::value;
const int c = tmax<list[0],list[1]>::value; // works fine now

これが機能する理由について:

const int a = list[2]; // this doesn't error?

変数の初期化にconst定数式は必要ありません。

int foo(int n) {
    const int a = n; // initializing const var with a non-compile time constant
于 2012-06-09T23:18:04.493 に答える
4

許可されていない多くのサブ式のいずれかが含まれている場合、その式は定数式ではありません。そのような許可されていない部分式のクラスの 1 つは、次のとおりです。

  • 適用されない限り、左辺値から右辺値への変換 (4.1)
    • 定数式で初期化された、前に初期化された不揮発性 const オブジェクトを参照する整数型または列挙型の glvalue、または
    • で定義された非揮発性オブジェクトconstexprを参照する、またはそのようなオブジェクトのサブオブジェクトを参照するリテラル型の glvalue、または
    • 定数式で初期化された、存続期間が終了していない不揮発性の一時オブジェクトを参照するリテラル型の glvalue。

特に、定数初期化子で初期化された enum または integral 型の const オブジェクトの名前は定数式を形成しますが (その値を読み取ると、左辺値から右辺値への変換が行われます)、const 集約オブジェクトのサブオブジェクト (そのようなあなたの例のようlistに、配列)はしませんが、宣言された場合はそうしconstexprます。

const int list[3] = { 2, 5, 7 };
const int a = list[2];

これは有効ですが、定数で初期化されていないため、定数式をa構成しません。

の宣言を変更することでlist( の宣言を変更する必要はありませんa)、aform を定数式にすることができます。

constexpr int list[3] = { 2, 5, 7 };
const int a = list[2];

list[2]定数式になりましたaが、定数式で初期化された整数型のconstオブジェクトになり、定数式としてa使用できるようになりました。

于 2012-06-09T23:35:50.527 に答える