鍋あり谷あり

テーマを決めずに適当に書いています。

デフォルト引数の不思議な世界

C++のデフォルト引数で、ちょっと変なことができることに気がついた。

ostream & f(int,ostream &){ return cout <<"f"; }

template<typename anytype>
ostream & f(anytype){ return cout << "t"; }

void test()
{
  f(0) << "\n"; // t
  ostream & f( int,ostream & = f(0) );
  f(0) << "\n"; // tf
  {
    ostream & f( int,ostream & = f(0) );
    f(0) << "\n"; // tff
    {
      ostream & f( int,ostream & = f(0) );
      f(0) << "\n"; // tfff
    }
  }
}

最初のf(0)<<"\n"は、テンプレート版を呼ぶ。
次のf(0)<<"\n"は、直前の宣言により、非テンプレート版が呼ばれるが、その前にデフォルト引数としてテンプレート版が呼ばれる。従って、出力は tf となる。
その次のf(0)<<"\n"は、やはり非テンプレート版が呼ばれるんだが、その前に呼ばれるデフォルト引数としては、ひとつ外側のスコープで定義された非テンプレート版が呼ばれる。その非テンプレート版はデフォルト引数としてテンプレート版を呼ぶので、出力は tff となる。
最後のやつは、同じ論理で tfff となる。

もうすこし考えればもっと気持ち悪いことができそうな気がしてならないんだが、今日のところはこれぐらいで。