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 指定子を指定して宣言することはできません。