新しい標準がmin(a,b)
とmax(a,b)
なしconstexpr
を定義していることに気づきました。
25.4.7、[alg.min.max]の例:
template<class T> const T& min(const T& a, const T& b);
template<class T> T min(initializer_list<T> t);
これは残念ではありませんか?書きたかったのに
char data[ max(sizeof(A),sizeof(B)) ];
の代わりに
char data[ sizeof(A) > sizeof(B) ? sizeof(A) : sizeof(B) ];
char data[ MAX(sizeof(A),sizeof(B)) ]; // using a macro
それらの理由constexpr
にすることはできません?
以下の分析は間違っています。1つの重要なことを混乱させるからです。私が行った次のステートメントは、まったく異なる答えを必要とする1つの重要な詳細を見逃していました。
名前のない参照
max
が返すのは、そのオペランドを参照します。
ここでの問題は、関数呼び出し置換がその時点で完了であるということです。呼び出しの置換に、max
が生成するそのglvalueの左辺値から右辺値への変換が含まれる場合、静的ストレージ期間ではない一時的なものを参照するglvalueからの読み取りは問題ないため、すべてが問題ありません定数式の計算中。ただし、読み取りは関数呼び出し置換の外部で行われるため、関数呼び出し置換の結果はlvalueになります。仕様のそれぞれのテキストは言う
参照定数式は、静的ストレージ期間または関数を持つオブジェクトを指定する左辺値コア定数式です。
ただし、max
が返す参照は、指定されていない保存期間のオブジェクトを指定する左辺値を生成します。単なるコアではなく、定数式を生成するには、関数呼び出しの置換が必要です。 )定数式。したがって、max(sizeof(A), sizeof(B))
が機能することは保証されていません。
以下の(古い)テキストは上記を考慮して読む必要があります。
constexpr
をそこに貼り付けたくない理由は今のところわかりません。とにかく、次のコードは間違いなく便利です
template<typename T> constexpr
T const& max(T const& a, T const& b) {
return a > b ? a : b;
}
他の答えが書いていることに反して、これは合法だと思います。 max
のすべてのインスタンス化がconstexpr関数である必要はありません。現在のn3242は言う
Constexpr関数テンプレートまたはクラステンプレートのメンバー関数のインスタンス化されたテンプレートの特殊化がconstexpr関数またはconstexprコンストラクターの要件を満たさない場合、その特殊化はconstexpr関数またはconstexprコンストラクターではありません。
テンプレートを呼び出すと、引数の推論により、関数テンプレートの特殊化が生成されます。これを呼び出すと、関数呼び出し置換がトリガーされます。次の呼び出しを検討してください
int a[max(sizeof(A), sizeof(B))];
最初に、2つのsize_t
prvalueを2つの参照パラメーターに暗黙的に変換し、両方の参照をそれらの値を格納する一時オブジェクトにバインドします。この変換の結果は、一時オブジェクトを参照する各ケースのglvalueです(4p3を参照)。これで、関数呼び出し置換は、これら2つのglvalueを受け取り、関数本体で発生するすべてのa
とb
をそれらのglvalueで置き換えます。
return (<glval.a>) > (<glval.b>) ? (<glval.a>) : (<glval.b>);
この条件では、5.19p2で許可されている、これらのglvalueの左辺値から右辺値への変換が必要になります。
- 定数式で初期化された非揮発性の一時オブジェクトを参照するリテラル型のglvalue
条件式は、第1オペランドまたは第2オペランドのいずれかにglvalueを生成します。名前のない参照max
が返すのは、そのオペランドを参照します。また、配列の次元サイズの指定で行われる最終的な左辺値から右辺値への変換は、上記で引用したのと同じルールによって有効になります。
initializer_list
には現在constexpr
メンバー関数がないことに注意してください。これは既知の制限であり、C++ 0x以降で処理されるため、これらのメンバーはconstexpr
になる可能性があります。
std :: minおよびstd :: max constexpr C++ 14では、これは明らかに、それらをconstexprにしない正当な理由(最近)がないことを意味します。問題が解決しました :-)
std::min()
およびstd::max()
のconstexpr
バージョンがC++ 14に含まれていることは、これらの関数(のバージョン)をconstexpr
にすることに根本的な障害がないことを示しています。 constexpr
がC++ 11に追加されたとき、これは十分に早く考慮されていなかったようです。
明らかに、比較関数が提供されているバージョンの場合、テンプレートの展開を成功させるには、その関数自体がconstexpr
である必要があります。