【C++】auto型の仮引数や戻り値を宣言する方法

C++ではautoキーワードによる仮引数宣言を行うことができない。

void f(auto v) {} // error: 'auto' not allowed in function prototype

ただ、「# テンプレート仮引数」や「# ジェネリックラムダ」を用いることで、auto型の仮引数を実現することができる。

目次

テンプレート仮引数

テンプレート関数でテンプレート仮引数を宣言することで、仮引数型の推論を実現することができる。

template<class T> void f(T v) { printf("%zu\n", sizeof v); };

int main() {
  f(1);   // "4"
  f(1L);  // "8"
  f('c'); // "1"
  f(0.f); // "4"
  f(0.0); // "8"
}

ちなみに上記のような関数宣言は、クラスのメンバ関数に対しても活用できる。

ジェネリックラムダ

C++14ではラムダ式の仮引数にautoを指定することができる。

auto f = [](auto v) { printf("%zu", sizeof v); };

int main() {
  f(1);   // "4"
  f(1L);  // "8"
  f('c'); // "1"
  f(0.f); // "4"
  f(0.0); // "8"
}

ラムダ式は関数オブジェクトの糖衣構文を実現する機能であるため、内部的にはテンプレート仮引数と()演算子オーバロードを活用した以下のような定義と同等のことが行われていることになる。

struct closure_object {
  template<class T> void operator()(T v) const { printf("%zu\n", sizeof v); }
};

// auto f = [](auto v) { printf("%zu", sizeof v); };
closure_object f; // ↑と同等の宣言

int main() {
  f(0.f); // "4"
  f(0.0); // "8"
}

auto型の戻り値

C++11以前のコンパイラでは戻り値に対するautoキーワードの指定は行えない。

/* C++03 */
// error: 'auto' not allowed in function return type
auto f() { return 9; }

/* C++11 */
// error: 'auto' return without trailing return type; deduced return types are a C++14 extension
auto f() { return 9; }

C++14であれば戻り値の型推論が行われるため、戻り値型にautoを利用することができる(-std=c++14コンパイラオプションでコンパイル可能)。

ただし、C++11の場合は戻り値の後置記法を用いて、-> decltype(推定対象の式)による記法を用いる必要がある。

// 戻り値型はint型
auto f() -> decltype(9) { return 9; }
auto f() -> decltype(9)   { return 0; } // int  f();
auto g() -> decltype('c') { return 0; } // char g();
auto h() -> decltype(g()) { return 0; } // char h();

printf("%zu%zu%zu", sizeof f(), sizeof g(), sizeof h()); // "411"
広告