2016-06-14 6 views
3

私は(VS2015)次のテンプレート控除が動作しない理由として興味:上記の例でテンプレートメンバ関数の引数控除

template<typename T> 
class Foo 
{ 
public: 
    template<typename U> 
    U get(U u) { return u; } 

    // Default constructed U and T for example only. 
    template<typename U> 
    U get(std::function<U(U, T)> f) { return f(U(), T()); } 

    template<typename U> 
    U get(U u, std::function<U(U,T)> f) { return u; } 

}; 

は、次のように成功する:

Foo<int> f; 
auto f_asInt = f.get(5);  // f_asInt is of type int 
auto f_asFloat = f.get(5.0f); // f_asFloat is of type float. 

auto ff_asInt = f.get([](int, int) { return 5; }); 
auto ff_asFloat = f.get([](float, int) { return 5.0f; }); 

次は、しかし、私は次のエラーを取得しています

Foo<int> f; 
auto f_asInt = f.get(5, [](int, int) { return 5; }); 
auto f_asFloat = f.get(5.0f, [](float, int) { return 5.0f; }); 

のコンパイルに失敗します。

error C2784: 'U Foo<int>::get(U,std::function<U(U,T)>)': could not deduce template argument for 'std::function<U(U,T)>' from 'main::<lambda_c4fa8cb1e6fa86997f25b7dabd5d415f>' 

テンプレート全体を入力すると、期待通りに機能します。

Foo<int> f; 
auto f_asInt = f.get<int>(5, [](int, int) { return 5; }); 
auto f_asFloat = f.get<float>(5.0f, [](float, int) { return 5.0f; }); 

テンプレート引数がこの場合に推測されることを希望します。それは可能ですか?

+0

私はVS2015に留意すべきでした。 – lcs

+2

@SergeyA「コンパイルする」部分はどれですか?通常の理由から、これはコンパイルすべきではありません。 –

+0

@SergeyA:clangとgccの両方で失敗する[デモ](http://coliru.stacked-crooked.com/a/8985d5f62d8f258e)。 – Jarod42

答えて

4

std::functionタイプはラムダから推測できないため動作しません。コンパイラは、Fstd::function<F>が与えられたラムダからどのようなものであるかを知る方法がありません。最初のブロックの最後の2つの例は、get(U u)オーバーロードが使用されていて、std::function引数を使用していないためにのみ機能します。

ラムダを受け入れるには、std::functionではなく一般的な呼び出し可能な型を受け入れるオーバーロードが必要です。あなたがしようとしていることを説明しない限り、より具体的な方向を示すのは難しいです。

関連する問題