私は正しいですか:
constexpr
で定義された関数はすべて純粋な関数であり、constexpr
コンパイラにとって非常に高価でない場合、任意の純粋な関数を定義することができ、定義する必要があります。
もしそうなら、なぜ arent<cmath>
の関数が で定義されているのconstexpr
でしょうか?
他の人が言ったことに追加するには、次のconstexpr
関数テンプレートを検討してください。
template <typename T>
constexpr T add(T x, T y) { return x + y; }
このconstexpr
関数テンプレートは、場合によっては定数式で使用できますが (例: where T
is int
)、他の場合 (例: where isは宣言されていないオーバーロードをT
持つクラス型) では使用できません。 operator+
constexpr
constexpr
関数が定数式で常に使用できるという意味ではなく、関数が定数式で使用できる可能性があることを意味します。
(非テンプレート関数を含む同様の例があります。)
前の回答に加えて、関数の constexpr はその実装を大幅に制限します。その本体はコンパイラ (インライン) から見える必要があり、単一の return ステートメントのみで構成されている必要があります。sqrt() または sin() を正しく実装して、最後の条件を満たしているとしたら、私は驚きます。
constexpr
関数は、引数が定数であり、これらの引数について関数の本体で言及されている操作自体がである場合、コンパイル中に関数が計算される可能性があるというコンパイラへのヒントであるpure
ためではありません。constexpr
constexpr
後者は、テンプレートコードを使用して、不純なconstexpr
関数を示すことができます。
template <typename T>
constexpr T add(T lhs, T rhs) { return lhs + rhs; }
このタイプでインスタンス化
DebugInteger operator+(DebugInteger lhs, DebugInteger rhs) {
printf("operator+ %i %i", lhs._value, rhs._value);
return DebugInteger(lhs._value + rhs._value);
}
ここでは、operator+
はconstexprではないため、グローバル状態の読み取り/書き込みが可能です。
constexpr
関数はコンパイル時に評価されると言うことができますpure
...しかし、実行時間に関する限り、関数は単に定数に置き換えられます。
すべてのconstexpr
関数は純粋ですが、すべての純粋関数が であるわけではありませんconstexpr
。
[constexpr
関数テンプレートを含む例は誤解を招きます。関数テンプレートは関数ではなく、コンパイラが関数を生成できるパターンであるためです。関数テンプレートの結果、その特殊化は関数であり、可能性は低いでしょうconstexpr
。]
純粋関数とは、その引数またはその他の定数状態のみに依存する関数です。それはほとんどconstexpr
関数です。さらに、constexpr
関数は最初に使用する前に (宣言するだけでなく) 定義する必要があり (ただし、再帰は許可されているようです)、return ステートメントのみで構成する必要があります。これは、許可されたサブセットをチューリング完全にするのに十分ですが、実行時に必ずしも結果が最も効率的な形式になるとは限りません。
これにより、数学関数が表示されます。おそらくconstexpr
sqrt()
orsin()
を実装できますが、コンパイラがコンパイル時に評価できる再帰的な実装を使用する必要がありますが、実行時には、これらは 1 つのアセンブラー操作で実装する方が適切です。とconstexpr
の使用はほとんどなく、かなり離れているため、代わりに実行時のパフォーマンスを最大化することをお勧めします。これには、実行できないフォームが必要です。sqrt()
sin()
constexpr
関数の1 つのバージョンと実行時に使用されるバージョンを作成できないのはなぜかと思うかもしれません。constexpr
それがあればいいのですが、標準では、constexpr
ness をオーバーロードできないと書かれています。おそらくC++ 17で...