クライアントコードがあなたが約束している以上のものを期待するのを防ぐ
ライブラリを作成していて、現在定数を返す関数がそこにあるとします。
awesome_lib.hpp
:
inline int f() { return 4; }
必要がない場合constexpr
は、クライアントコードの作成者であるあなたが立ち去って次のようなことをする可能性があります。
client_app.cpp
:
#include <awesome_lib.hpp>
#include <array>
std::array<int, f()> my_array; // needs CT template arg
int my_c_array[f()]; // needs CT array dimension
次にf()
、構成ファイルから値を返すように変更すると、クライアントコードが壊れますが、コードが壊れてしまうリスクがあるとは思いません。実際、本番環境に問題があり、再コンパイルに行く場合にのみ、この追加の問題が再構築を妨げることに気付く可能性があります。
の実装のみを変更することで、インターフェースf()
の使用法を効果的に変更できたはずです。
代わりに、C ++ 11以降が提供するconstexpr
ので、クライアントコードは、関数がaのままであるという合理的な期待を持ち、constexpr
それをそのまま使用できることを示すことができます。 私は自分のインターフェースの一部としてそのような使用法を認識し、承認しています。 C ++ 03の場合と同様に、コンパイラは、constexpr
上記の「不要な/不明な依存関係」シナリオを防ぐために、クライアントコードが他の非関数に依存するように構築されていないことを保証し続けます。これはドキュメント以上のものです-コンパイル時の強制です。
これは、プリプロセッサマクロの従来の使用法のより良い代替手段を提供するというC ++の傾向を継続していることは注目に値します(#define F 4
クライアントプログラマーが、libプログラマーが言うことを変えるのが公正なゲームであると見なすかどうかをどのように知るかを検討してください#define F config["f"]
)。言語の名前空間/クラススコープシステムの外にあるものとして。
「明らかに」決して定数ではない関数の診断がないのはなぜですか?
constexpr
ここでの混乱は、結果が実際にコンパイル時の定数である引数のセットがあることを積極的に保証していないためだと思います。むしろ、プログラマーがその責任を負う必要があります(そうでない場合は標準の§7.1.5/5プログラムの形式が正しくないと見なされますが、コンパイラーが診断を発行する必要はありません)。はい、それは残念ですが、上記のユーティリティを削除するものではありませんconstexpr
。
したがって、「実際にはconst値を返すことができない関数をコンパイルできるのはなぜですか」という質問から、 「何が重要なのconstexpr
か」という質問に切り替えると役立つかもしれません。。constexpr
回答:任意の数の組み合わせを含む可能性のある徹底的なブランチ分析が必要になるためです。診断するのは、コンパイル時間やメモリ(想像できるハードウェアの能力を超えていても)で非常にコストがかかる可能性があります。さらに、そのようなケースを正確に診断しなければならないことが実際的である場合でも、コンパイラの作成者(彼らの時間のより良い使用法を持っている)のためのまったく新しいワームの缶です。constexpr
また、検証が実行されたときに表示される必要がある関数内から呼び出された関数(および関数が呼び出す関数など)の定義など、プログラムにも影響があります。
一方、const値としての使用はconstexpr
引き続き禁止されており、厳格さは重要ではありませんconstexpr
。上に示したように、これは便利です。
非`const`メンバー関数との比較
constexpr
防止int x[f()]
しますが、const
防止しませんconst X x; x.f();
-どちらも、クライアントコードが不要な依存関係をハードコーディングしないようにします
どちらの場合も、コンパイラが-nessを自動的に決定することは望ましくありませんconst[expr]
。
それらは、コンパイラーがメンバー関数内で他のメンバーの使用を強制するという点で異なりますが、コンパイル時定数の結果を強制しません(実際のコンパイラーの制限のため)const
const
constexpr