2015-01-08 4 views
9

次のプログラムは違法である、と私は理解したい理由:std ::関数をとるこの関数にラムダを渡すことができないのはなぜですか?

#include <functional> 
#include <iostream> 

template<typename Result, typename Arg> 
void deduce(std::function<Result(Arg)> f) 
{ 
    std::cout << "Result: " << typeid(Result).name() << std::endl; 
    std::cout << "Arg: " << typeid(Arg).name() << std::endl; 
} 


int main() 
{ 
    auto f = [](int x) 
    { 
    return x + 1; 
    }; 

    deduce(f); 

    return 0; 
} 

clangの出力:

$ clang -std=c++11 test.cpp 
test.cpp:48:3: error: no matching function for call to 'deduce' 
    deduce(f); 
    ^~~~~~ 
test.cpp:26:6: note: candidate template ignored: could not match 'function<type-parameter-0-1 (type-parameter-0-0)>' against '<lambda at test.cpp:34:13>' 
void deduce(std::function<T2(T1)> f) 
    ^
1 error generated. 

それは私がstd::functionに私のラムダを変換することができるはずであるように思えますdeduceで受信しました。この場合、コンパイラが適切な変換を適用できないのはなぜですか?

答えて

5

問題がintを取り、intを返すラムダstd::function<int(int)>に変換することができるが、その種類はないstd::function<int(int)>であるが、任意の実装定義タイプと思うことがあります。

この問題を回避するには、コンパイラに必要なタイプを伝えます。変換が期待どおりに行われます。

auto f = [](int x){ return x + 1; }; 
deduce<int, int>(f); // now ok 

また、静的タイプfを明示する必要があります。

std::function<int(int)> f = [](int x){ return x + 1; }; 
deduce(f); // now also ok 
+0

ありがとうございました。私は型が同じではないことを理解していますが、コンパイラがここで適切な変換を適用できない理由を理解しようとしています。 –

+2

問題は、引数の値の変換ではなく、テンプレートパラメータの控除です。一度(私が与えた最初のスニペットのように)それらがわかっていれば、変換は正常です。私はここで有効なルールを正確に調べることができるかどうか試してみる。 – 5gon12eder

+1

はい、控除が問題です。これは、正確な控除でなければなりません。なぜなら、すべての専門化は、必要な変換を行うことも、できないこともあるからです。 – Deduplicator

関連する問題