constexpr (C++)
キーワード constexpr
が C++11 で導入され、C++14 で改良されました。 これは、constAnt 式を意味します。 const
のように、変数にそれを適用することができます。コードが値をif変更しようとしたときにコンパイラ エラーが生成されます。 const
とは異なり、constexpr
は関数やクラス const のコンストラクターにも適用できます。 constexpr
は値または戻り値が constant であることを示し、可能な場合はコンパイル時に計算されます。
constexpr
整数値は、テンプレート引数や配列の宣言など、const の整数値が必要な場所で使用できます。 実行時ではなくコンパイル時に値を計算すると、プログラムをより高速に実行して、使用するメモリを少なくするのに役立ちます。
コンパイル時の constant 計算の複雑さと、コンパイル時の潜在的な影響を制限するために、c++ 14 標準では、constant 式の型がリテラル型である必要があります。
構文
constexpr
literal-typeidentifier=constant-expression;
constexpr
literal-typeidentifier{constant-expression};
constexpr
literal-typeidentifier(params);
constexpr
ctor(params);
パラメーター
params
1つ以上のパラメーター。それぞれがリテラル型である必要があり、それ自体が constant 式でなければなりません。
戻り値
constexpr
変数または関数は、リテラル型を返す必要があります。
constexpr 変数
const
変数と constexpr
変数の間の主な if 違いは、const
変数の初期化を実行時まで遅らせることができることです。 constexpr
変数は、コンパイル時に初期化する必要があります。 すべての constexpr
変数は const
です。
変数がリテラル型で初期化されている場合は、
constexpr
で宣言できます。 初期化がconstコンストラクターによって実行forされる場合、constコンストラクターはconstexpr
として宣言する必要があります。参照は、両方の条件が満たされたときに
constexpr
として宣言できます。参照されるオブジェクトは、const ant 式によって初期化されます。また、初期化中に呼び出された暗黙の変換も const ant 式になります。constexpr
変数または関数のすべての宣言は、constexpr
指定if子を持っている必要があります。
constexpr float x = 42.0;
constexpr float y{108};
constexpr float z = exp(5, 3);
constexpr int i; // Error! Not initialized
int j = 0;
constexpr int k = j + 1; //Error! j not a constant expression
constexpr 関数
constexpr
関数は、使用側コードが必要とする場合に、戻り値をコンパイル時に計算できます。 コードを使用するには、コンパイル時に constexpr
変数を初期化するか、非型テンプレート引数を指定する必要があります。 引数が constexpr
値の場合、constexpr
関数はコンパイル時に constant を生成します。 非 constexpr
引数を使用して呼び出されたとき、または値がコンパイル時に必要でない場合には、正規関数のように、実行時に値を生成します。 (この 2 重の動作により、同じ関数の constexpr
と非 constexpr
のバージョンを記述する手間が省けます。)
constexpr
関数またはconstコンストラクターは暗黙的に inline
です。
constexpr 関数には次の規則が適用されます:
constexpr
関数はリテラル型のみを受け入れて返す必要があります。constexpr
関数は再帰的にすることができます。fore C++20 であり、関数を
constexpr
仮想にすることはできません。またconst、外側のクラスに仮想基底クラスがある場合と同様constexpr
に、ルクターを定義することはできません。 C++20 以降では、関数をconstexpr
仮想にすることができます。 Visual Studio 2019 バージョン 16.10 以降のバージョンでは、y 以降のコンパイラ オプションを指定ifした場合に仮想関数が/std:c++20
サポートconstexpr
されます。本体は
= default
または= delete
として定義できます。本文には、
goto
ステートメントまたはtry
ブロックを含めることはできません。constexpr
ではないテンプレートの明示的な特殊化はconstexpr
として宣言できます:constexpr
テンプレートの明示的な特殊化は、constexpr
である必要はありません:
Visual Studio 2017 以降の constexpr
関数には、次の規則が適用されます。
これには、
if
ステートメントとswitch
ステートメント、および、for
、範囲ベースfor
、while
、および do-while を含むすべてのループ ステートメントを含めることができます。ローカル変数宣言が含まれている場合がありますが、変数を初期化する必要があります。 リテラル型である必要があり、
static
またはスレッド ローカルにすることはできません。 ローカルで宣言された変数は、const
である必要はなく、変化する可能性があります。constexpr
非static
メンバー関数は、暗黙的const
に指定する必要はありません。
constexpr float exp(float x, int n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp(x * x, n / 2) :
exp(x * x, (n - 1) / 2) * x;
}
ヒント
Visual Studio デバッガーでは、最適化されていないデバッグビルドをデバッグするときに、コンパイル時に constexpr
関数が評価されているかどうかを、その中にブレークポイントを配置することで判断できます。 ブレークポイントにヒットすると、実行時に関数が呼び出されます。 ヒットしなければ、コンパイル時に関数が呼び出されます。
extern constexpr
/Zc:externConstexpr コンパイラ オプションを指定すると、コンパイラで extern constexpr が使用され、宣言された変数に外部リンケージが適用されます。 Visual Studio の以前のバージョンでは、既定で、または /Zc:externConstexpr- が指定されている場合、extern
キーワードが使用されている場合でも、Visual Studio によって constexpr
変数に内部リンケージが適用されます。 /Zc:externConstexpr オプションは、Visual Studio 2017 Update 15.6 から使用できます。既定ではオフになっています。 /permissive- オプションでは、/Zc:externConstexpr は有効になりません。
例
次の例は constexpr
変数、関数、およびユーザー定義の型を示します。 main()
の最後のステートメントでは、コンパイル時に値が既知である必要はないため constexpr
メンバー関数 GetValue()
は実行時の呼び出しです。
// constexpr.cpp
// Compile with: cl /EHsc /W4 constexpr.cpp
#include <iostream>
using namespace std;
// Pass by value
constexpr float exp(float x, int n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp(x * x, n / 2) :
exp(x * x, (n - 1) / 2) * x;
}
// Pass by reference
constexpr float exp2(const float& x, const int& n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp2(x * x, n / 2) :
exp2(x * x, (n - 1) / 2) * x;
}
// Compile-time computation of array length
template<typename T, int N>
constexpr int length(const T(&)[N])
{
return N;
}
// Recursive constexpr function
constexpr int fac(int n)
{
return n == 1 ? 1 : n * fac(n - 1);
}
// User-defined type
class Foo
{
public:
constexpr explicit Foo(int i) : _i(i) {}
constexpr int GetValue() const
{
return _i;
}
private:
int _i;
};
int main()
{
// foo is const:
constexpr Foo foo(5);
// foo = Foo(6); //Error!
// Compile time:
constexpr float x = exp(5, 3);
constexpr float y { exp(2, 5) };
constexpr int val = foo.GetValue();
constexpr int f5 = fac(5);
const int nums[] { 1, 2, 3, 4 };
const int nums2[length(nums) * 2] { 1, 2, 3, 4, 5, 6, 7, 8 };
// Run time:
cout << "The value of foo is " << foo.GetValue() << endl;
}
必要条件
Visual Studio 2015 またはそれ以降。
関連項目
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示