2011-01-05

constexpr関数とテンプレートについて

Twitter / 妖精闇姫 非実在えつえつしーりつく: @kikairoya http://ideone.c ...
Twitter / 妖精闇姫 非実在えつえつしーりつく: template の行を削るとちゃんと(?)コンパイ ...
Ideone.com | Online C++0x Compiler & Debugging Tool

以下のコードを考える。

int g = 0;
 
template< typename T = void >
constexpr int f()
{
    return g;
}
 
int main()
{
    std::cout << f() << std::endl; // 0
    g = 1;
    std::cout << f() << std::endl; // 1
}

これは、一見すると、constexpr関数で、定数でもないstatic変数gを、constexpr関数の中から扱っているように見える。これはエラーにならない。しかし、テンプレートを外すと、エラーになる。何故ならば――

constexpr関数が、関数テンプレートのとき、テンプレートのインスタンス化の結果、constexpr関数の要件を満たさなくなった場合、その関数はconstexprではなくなる。

――からだ。インスタンス化が、constexprの要件をみたいしていないので、関数fは、通常の関数になる。もちろん、関数呼び出しは、定数式ではなくなる。たとえば、以下のようなコードは、エラーになる。

constexpr int x = f() ; // エラー、constexpr変数は、非定数式で初期化できない

2 comments:

RiSK said...
This comment has been removed by the author.
RiSK said...

typoったのでやり直し。

ツイートの捕捉および解説ありがとうございます。
テンプレート関数の場合は特殊なんですねぇ。


>通常の間数

通常の関数