読者です 読者をやめる 読者になる 読者になる

C++14 で関数テンプレートを変数や関数に渡すときにテンプレート型を明示化するのを回避する

C++ で関数テンプレートを変数や関数に渡す場合は、渡すときにテンプレート型を明示化する必要があります。

template<typename T, typename U>
auto
plus(T a, U b){
    return a + b;
}


// こういう風に渡すことはできない
// auto f = &plus;
// 変数に渡す場合はテンプレート引数を明示化する必要がある
auto f = &plus<int, int>;


// // 関数に渡す場合も同じ
auto f2 = std::bind(plus<int, int>, 10, std::placeholders::_1);
f(4); // => 14

// 当然、別の型を渡しても int として扱われる
f(3.14); // => 13

これだと関数テンプレートを呼び出す前にテンプレート型を決定する必要があるのでかなり不便ですね。

[C++14 で実装された多相ラムダで回避する]

C++14 以前では、こういう問題を回避する場合は関数オブジェクトでラップしていました、C++14 で実装された多相ラムダを使うことで簡単に回避する事ができます。

template<typename T, typename U>
auto
plus(T a, U b){
    return a + b;
}

// 多相ラムダを使ってラップしてやる
auto f = [](auto.. args){ return plus(args...); };

// これでどんな型も渡すことができる
f(1, 2); // => 3
f(3.2, -1.4); // => 1.8

// std::bind に渡してみたり
using std::placeholders::_1;
auto f2 = std::bind([](auto... args){ return plus(args...); }, 10, _1);
f2(3.14); // => 13.14

毎回ラムダ式でラップするのはちょっと手間ですが、関数オブジェクト化するよりは全然楽ですね。
多相ラムダ便利。