2016-12-28 20 views
1

は、次のことを考えてみましょう:ラムダを引数として渡したテンプレート関数の関数型パラメータを推測するには?

#include <utility> 
#include <string> 

template<typename> 
class C; 

template<typename R, typename T> 
class C<R(&)(T)> { 
public: 
    template<typename F> 
    C(F&& fun) {} 
}; 

template<typename T> 
C<T> makeC(T&& fun) { 
    return C<T>(std::forward<T>(fun)); 
} 

int foo(int a){return a;} 

int main() { 
    auto p1 = makeC(foo); // OK 
    auto p2 = C<int(&)(int)>([](int a){return a;}); // OK 
    // auto p3 = makeC([](int a){return a;}); // FAIL 
} 

Live example

コンパイラがパラメータとして渡されたラムダからタイプint(&)(int)を推測することはできませんのでp3の宣言が失敗しました。 p1は、タイプが明示的に宣言されているので、タイプがfooから容易に推測できるのでOKです。p2はOKです。それはで失敗

error: invalid use of incomplete type 'class C<main()::<lambda(int)> >'

は、コンパイラがcorretly関数の型を推論させるためにどのような方法は、ラムダ与えられた、ありますか?

P .: C++ 17回答も該当する場合は大丈夫です。

+1

http://stackoverflow.com/questions/21657627/what-is-the-type-signature-of-a-c11-1y-lambda-function – LogicStuff

答えて

1

ラムダ関数には独自の型があり、それをR(&)(T)に減らすことはできません。そのため、C<T>は、コンパイラによって正しく説明されているように、不完全な型です。

auto p3 = makeC(*(+[](int a){return a;})); 

またはこの:

template<typename T> 
auto makeC(T&& fun) -> C<decltype(*(+std::forward<T>(fun)))> { 
    return C<decltype(*(+std::forward<T>(fun)))>(std::forward<T>(fun)); 
} 


限り、あなたは非キャプチャラムダを使用して、あなたは彼らが関数ポインタと、これを行うために崩壊するという事実に頼ることができますラムダをキャプチャするのに有効な別の解決策は次のとおりです。

#include <utility> 
#include <string> 

template<typename T> 
class C: T { 
    template<typename F> 
    C(F&& fun): T{std::forward<F>(fun)} {} 
}; 

template<typename R, typename T> 
class C<R(&)(T)> { 
public: 
    template<typename F> 
    C(F&& fun) {} 
}; 

template<typename T> 
C<T> makeC(T&& fun) { 
    return C<T>(std::forward<T>(fun)); 
} 

int foo(int a){return a;} 

int main() { 
    auto p1 = makeC(foo); 
    auto p2 = C<int(&)(int)>([](int a){return a;}); 
    auto p3 = makeC([](int a){return a;}); 
} 

このようにラムダを扱う場合、Cは実際にそれを継承し、私的にはにはoperator()が含まれます。

+1

偉大な答え、ありがとう!あなたの最終的な解決策は素晴らしいですが、残念ながら私はテンプレートインスタンスのラムダのパラメータタイプを区別できる必要があります。私は私のシナリオではひどい制限ではないので、キャプチャしていないラムダをサポートすることだけに固執すると思います。 –

関連する問題