What is it, naokirin?

C++0xの戻り値型の後方宣言

後方宣言でどのようなことができるのかについて考えてみる。
たとえば、型TとUを引数にとり、その二つの引数をoperator*()で計算する関数を考えてみる。

後方宣言を使わずに書こうとすると

template<class T, class U>
decltype(*(T*)(0)**(U*)(0)) foo(T x, T y)
{ ... }

のようになる。(ちょっとこればかりは怪しげなコードで、間違えそうで怖い。そしてあってるのかも怖いコード。こんなコード書いたことないので、C++0xのページにあったコードをそのまま持ってきています。)言ってしまえば、

decltype(*(T*)(0)**(U*)(0))

はT*型とU*型のオブジェクト(T*)(0)と(U*)(0)を値型に戻した*(T*)(0)と*(U*)(0)の型TとUを引数に取るoperator*の戻り値の型、ということになります。(…のはず。すごく自信がない。)

g++などで実行してみると、参照型をとる場合などにこのような方法でなければならないことが分かると思います。


上のコードがC++0xラムダ式とdecltypeを合わせて用いることで次のようなコードを書けるというものです。

template<class T, class U>
auto foo(T x, U y) -> decltype(x*y)
{
  return x*y;
}

戻り値型の指定をラムダ式で後ろに持っていっています。


しかしながら、これは正確には次のコード

template<class T, class U>
[] foo(T x, U y) -> decltype(x*y)
{ ... }

を、"[]"の部分を型推論"auto"に置き換えています。

ちなみにこのようなコードを書くために戻り値型の後置表記が導入されるわけではなく、スコープ問題を解決するためのものなのだそう。

私としては上の使い道ができるだけでも十分便利だとは思います。