constexpr 関数 (C++11)

注: IBM は、C++11 (承認前の呼称は C++0x) の、選定された機能をサポートしています。IBM は、この標準の機能の開発および実装を継続します。この言語レベルの実装は、IBM による標準の解釈に基づいています。 新しい C++11 標準ライブラリーのサポートを含め、すべての C++11 機能を IBM が実装し終えるまで、リリースごとに実装が変更される可能性があります。IBM では、IBM による新規 C++11 機能の実装に関し、ソース、バイナリー、リスト作成などのコンパイラー・インターフェースにおいて、以前のリリースとの互換性を維持するための試みは、特に行いません。

constexpr 指定子を指定して宣言される非コンストラクター関数は、constexpr コンストラクター関数です。 constexpr 関数は、定数式内で呼び出すことができる関数です。

constexpr 関数は、以下の条件を満たしている必要があります。
  • 仮想ではない。
  • 戻りの型がリテラル型である。
  • その各パラメーターは必ずリテラル型である。
  • 戻り値を初期化する際に、それぞれのコンストラクター呼び出しと暗黙的変換が定数式において有効である。
  • その関数本体が = delete または = default である。そうでない場合、その関数本体は以下のステートメントのみを含んでいる必要があります。
    • null ステートメント
    • static_assert 宣言
    • クラスまたは列挙を定義していない typedef 宣言
    • using ディレクティブ
    • using 宣言
    • 1 つの return ステートメント

コンストラクターではない非静的メンバー関数が constexpr 指定子を指定して宣言されている場合、メンバー関数は定数であり、constexpr 指定子には関数型に対するその他の効果はありません。 その関数がメンバーであるクラスは、リテラル型でなければなりません。

以下の例は、constexpr 関数の使用法を示しています。
const int array_size1 (int x) {
  return x+1;
}
// Error, constant expression required in array declaration
int array[array_size1(10)];    

constexpr int array_size2 (int x) { 
  return x+1; 
} 
// OK, constexpr functions can be evaluated at compile time
// and used in contexts that require constant expressions. 
int array[array_size2(10)];     

struct S {
  S() { }
  constexpr S(int) { }
  constexpr virtual int f() { // Error, f must not be virtual.
    return 55;
  }       
};

struct NL {
  ~NL() { }              // The user-provided destructor (even if it is trivial) 
                         // makes the type a non-literal type.
};

constexpr NL f1() {          // Error, return type of f1 must be a literal type.
  return NL();
}       

constexpr int f2(NL) {       // Error, the parameter type NL is not a literal type.
  return 55; 
}                 

constexpr S f3() {
  return S();
}

enum { val = f3() };         // Error, initialization of the return value in f3()
                             // uses a non-constexpr constructor.

constexpr void f4(int x) {   // Error, return type should not be void.
  return;
}

constexpr int f5(int x) {    // Error, function body contains more than return statement.
  if (x<0)
    x = -x;
  return x;
}
関数テンプレートが constexpr 関数として宣言された場合に、インスタンス化の結果として constexpr 関数の要件を満たさない関数が生成されるときには、constexpr 指定子は無視されます。 次に例を示します。
template <class C> constexpr NL f6(C c) {    // OK, the constexpr specifier ignored
  return NL();
}
void g() {
  f6(55); // OK, not used in a constant expression
}

constexpr 関数への呼び出しは、あらゆる点で、同等の非 constexpr 関数への呼び出しと同じ結果を生みます。ただし、constexpr 関数への呼び出しは定数式内に指定できるという点が異なります。

constexpr 関数は暗黙的にインラインになります。

main 関数は、constexpr 指定子を指定して宣言することはできません。