g++7.2.0とclang5.0.0で確認してたはず。
方法
constexprではない通常の関数にconstexpr変数を渡すことはできません。
// これはもちろんコンパイルエラー
void func(char const* x)
{
constexpr auto y = x;
}
int main()
{
constexpr auto x = "abc";
func( x );
}
そこで、C++17で追加されたconstexprラムダ式を使います。constexprラムダ式でconstexpr変数を包むことで、通常の関数でもconstexpr変数を渡すことができるようになります。
// これは通る
template <typename F>
void func(F f)
{
constexpr auto y = f();
}
int main()
{
// 明示的にconstexprラムダ式を書いた場合
func( []() constexpr { return "abc"; } );
// constexprラムダ式でもキャプチャできるので
constexpr auto x = "abc";
func( [&]{ return x; } );
}
条件を満たせばラムダ式のconstexprを暗黙にすることができる(N4659 [expr.prim.lambda.closure]/p4)ので、引数がない場合に()
を省略できることを合わせて、以下のように簡単にすることができます。
int main()
{
func( []{ return "abc"; } );
}
最後に
これを応用することで、printfのフォーマットのコンパイル時チェック等ができたりします。
・・・やっぱり本当にいいの、これ?
参考
ラムダ式を使って関数の引数からconstexpr変数を定義できたことに関する質問 - スタック・オーバーフロー
https://ja.stackoverflow.com/questions/38123/