2012年1月26日木曜日

戻り値型の後方宣言

関数の戻り値型を後方で宣言する

関数の宣言は、次のように2通りの記述が可能です。

// 1) 戻り値の宣言を、前方に記述する。
int add(int a, int b) {
  return a + b;
}
// 2) 戻り値の宣言を、後方に記述する。
auto add(int a, int b) -> int {
  return a + b;
}

なぜ2通りの記述方法があるのか不思議に思うかもしれません。1)の記述方法は、C言語から踏襲している記述方法です。2)の記述方法は1)では表現できない関数宣言を解消するためにC++で追加されました。

例えば、型が不明な2つの引数を取り、その加算結果を返す関数の場合、その戻り値の方が引数の型に依存してしまいます。なぜ戻り値の型が引数の型に依存するかというと、C++は演算子のオーバーライドができ、オーバーライドの定義によって戻り値の型を自由に指定できるからです。

そのような状況では、2つの引数の型と戻り値の型をテンプレート引数の指定するよりも、コンパイラに戻り値の型を解決させるほうが、その関数を簡単に使用することができます。

// テンプレート引数で戻り値の型を指定する場合
// P1とP2を加算した結果、戻り値の型が何になるかを関数を使用する人が考慮しなければならない
template <typename R, typename P1, typename P2>
R add(P1 a, P2 b) {
  return a + b;
}
// 戻り値の型をコンパイラに解決させるため、decltypeを使用する
template <typename P1, typename P2>
auto add(P1 a, P2 b) -> decltype(a + b) {
  return a + b;
}
// decltype(a + b)の引数a, bが解決できないため、以下のようには記述できない
template <typename P1, typename P2>
decltype(a + b) add(P1 a, P2 b) {
  return a + b;
}

戻り値型の後方宣言は、ラムダ関数でも使用する。詳しくはlambda式を参照して下さい。

0 件のコメント:

コメントを投稿