constexpr 指定子 (C++11)
注: IBM は、C++11 (承認前の呼称は C++0x) の、選定された機能をサポートしています。IBM は、この標準の機能の開発および実装を継続します。この言語レベルの実装は、IBM による標準の解釈に基づいています。
新しい C++11 標準ライブラリーのサポートを含め、すべての C++11 機能を IBM が実装し終えるまで、リリースごとに実装が変更される可能性があります。IBM では、IBM による新規 C++11 機能の実装に関し、ソース、バイナリー、リスト作成などのコンパイラー・インターフェースにおいて、以前のリリースとの互換性を維持するための試みは、特に行いません。
C++11 標準は、宣言指定子として新規キーワード constexpr を導入しています。
constexpr 指定子は、以下のコンテキストに対してのみ適用できます。
- 変数の定義
- 関数または関数テンプレートの宣言
- 静的データ・メンバーの宣言
constexpr int i = 1; // OK, definition
constexpr int f1(); // OK, function declaration, but must be defined before use
コンストラクターではない関数を constexpr 指定子を指定して宣言すると、その関数は constexpr 関数になります。
同様に、コンストラクターを constexpr 指定子を指定して宣言すると、そのコンストラクターは constexpr コンストラクターになります。
constexpr 関数と constexpr コンストラクターのどちらも、暗黙的にインラインになります。
次に例を示します。
struct S {
constexpr S(int i) : mem(i) { } // OK, declaration of a constexpr constructor
private:
int mem;
};
constexpr S s(55); // OK, invocation of a constexpr constructor
constexpr 指定子は、constexpr 関数または constexpr コンストラクターに対しては効力がありません。関数または関数テンプレートのいずれかの宣言が constexpr を使用して指定されている場合、そのすべての宣言には constexpr 指定子を含める必要があります。
次に例を示します。
constexpr int f1(); // OK, function declaration
int f1() { // Error, the constexpr specifier is missing
return 55;
}
関数仮パラメーターは、constexpr 指定子を指定して宣言することはできません。
次の例は、このことを示しています。
constexpt int f4(constexpr int); //Error
オブジェクト宣言内で使用される constexpr 指定子は、オブジェクトを const として宣言します。
このようなオブジェクトは、リテラル型で、初期化されていなければなりません。
これがコンストラクター呼び出しで初期化される場合、その呼び出しは定数式でなければなりません。
そうでない場合、constexpr 指定子が参照宣言内で使用されるのであれば、その初期化指定子に指定されるすべての完全式は、定数式でなければなりません。
初期化に用いる初期化指定子式と各コンストラクター呼び出しの変換に使用されるそれぞれの暗黙的な変換は、定数式内で有効でなければなりません。
次に例を示します。
constexpr int var; // Error, var is not initialized
constexpr int var1 = 1; // OK
void func() {
var1 = 5; //Error, var1 is const
}
struct L {
constexpr L() : mem(55) { }
constexpr L(double d) : mem((int)d) { }
L(int i) : mem(i) { }
operator int() { return mem; }
private:
int mem;
};
// Error, initializer involves a non-constexpr constructor.
constexpr L var2(55);
double var3 = 55;
// Error, initializer involves a constexpr constructor with non-constant argument
constexpr L var4(var3);
// Error, involves conversion that uses a non-constexpr conversion function
constexpr int var5 = L();
コンストラクターではない非静的メンバー関数の constexpr 指定子は、そのメンバー関数を const と宣言します。
その constexpr メンバー関数のクラスは、リテラル型でなければなりません。次の例では、クラス NL は、ユーザー提供のデストラクターを持っているため、非リテラル型です。
struct NL {
constexpr int f(){ //error, enclosing class is not a literal type
return 55;
}
~NL() { }
};
constexpr 関数への呼び出しは、同等の非 constexpr 関数への呼び出しと同じ結果を生みます。ただし、constexpr 関数への呼び出しは定数式内に指定できるという点が異なります。
main 関数は、constexpr 指定子を指定して宣言することはできません。