C++1zから、コンパイル時条件によって分岐するif constexpr
文が導入されます。これにより、再帰やヘルパ関数を書かなくて済むケースが多くなります。
D言語にあるstatic if
文のようなものです。
template <class T, class... Rest> void g(T&& p, Rest&&... rs) { if constexpr (sizeof...(rs) > 0) { g(rs...); // rs...が空のときのオーバーロードが不要 } }
else
の方にはconstexpr
は必要ありません。
テンプレート内で条件分岐した場合は、到達しなかったブロックはインスタンス化されません。
ただし、条件式内でのコンパイル時条件については全てインスタンス化され、短絡評価によって後ろの方の条件がインスタンス化されないことを期待するようなコードは書けないので注意してください。
if constexpr (has_value_type_v<T> && typename T::value_type())
このような条件式は、else節に進む場合にコンパイルエラーになります。このような条件を書きたい場合は、条件分岐を入れ子にする必要があります。
if constexpr (has_value_type_v<T>) { if constexpr (typename T::value_type()) { … } }
なお、constexpr if
でなくif constexpr
になっているのは、前者を採用すると構文として、else if
を書くときにconstexpr
が二重に必要になってしまうのを避けるためです。
// 採用された構文 if constexpr (cond) { } else if constexpr (cond) { } else { }
// 却下された構文 constexpr if (cond) { } constexpr else constexpr if (cond) { } constexpr else { }
最初に考えられていたstatic if
宣言と違って、if constexpr
文はスコープを導入します。また、型や関数を定義する条件分岐には使用できません。
// こういうことはできない。 // 条件によって関数や型の宣言・定義を変えるようなことはできないし、 // クラススコープでif constexpr文は使用できない struct X { if constexpr (cond) { void f(); using int32 = int; } else { void g(); } };
参照
- N3322 A Preliminary Proposal for a Static if
- N3329 Proposal:
static if
declaration - N3613 “Static If ” Considered
- Static If I Had a Hammer - Andrei Alexandrescu
- P0128R1
constexpr if
- P0292R2
constexpr if
: A slightly different syntax
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。