2017-02-01 11 views
3

ラムダをテンプレートパラメータとして渡す方法。このコードC++ラムダをテンプレートパラメータに渡す

template<void (*callback)()> 
void function() { 
    callback(); 
} 

int main() { 
    function<[]() -> void { std::cout << "Hello world\n"; }>(); 
} 

がエラー「コンパイル時の定数式が期待 『関数』の無効なテンプレート引数、」で失敗例えば

私は間違っています。私は一例で、この

template<typename T, 
     T (*deserializer)(buffer *data), 
     void (*serializer)(T item, buffer *data)> 
class Type { 
public: 
    T item; 

    Type(T item) : item(item) { 
    } 

    Type(buffer *data) { 
     deserialize(data); 
    } 

    void serialize(buffer *data) { 
     serializer(item, data); 
    } 

    void deserialize(buffer *data) { 
     deserializer(data); 
    } 
}; 

typedef Type<int, [](buffer* data) -> int { return -1; }, [](int item, buffer* data) -> void {}> IntType 

typedef Type<long, [](buffer* data) -> long { return -1; }, [](long item, buffer* data) -> void {}> LongType 
+0

'std :: for_each()'に従ってみませんか?テンプレート void f(F f){f(); } ' –

+0

私はクラステンプレートでこれを使用する予定です、これは単なるテストコードです。 – KoHcoJlb

+0

私は[その1](http://stackoverflow.com/questions/3810519/how-to-use-a-lambda-expression-as-a-template-parameter)の複製として質問を閉じるつもりでした。しかし質問も答えも恒星はありません... – Quentin

答えて

4

関数ポインタへの変換を含むLambdaは、constexprではありません。

C++ 17では、this is going to changeです。私が知っているその機能を実装した安定したコンパイラはありません(あなたが見つけたら、下記のコメントでそれを言えるでしょうか?)。その点

constexpr auto tmp = []() -> void { std::cout << "Hello world\n"; }; 
function<+tmp>(); 

は間違いなく動作します。私は不確かな場合

function<+[]() -> void { std::cout << "Hello world\n"; }>() 

が働くでしょう。評価されていない文脈やラムダ問題とは別のラムダのテンプレート引数リストにはいくつかの規則があり、ここで適用することができます。

C++ 14でハックすることができます。

ラムダの静的コピーを格納し、ラムダの静的コピーと呼ばれる同じシグネチャ(f_ptr)を持つ静的関数を公開するテンプレートクラスを作成します。

ラムダでグローバルに一度インスタンス化します。

テンプレートにf_ptrへのポインタを渡します。

ので:

template<class L> struct stateless; // todo 
template<class L> stateless<L> make_stateless(L l){return std::move(l);} 

auto foo = make_stateless([]() -> void { std::cout << "Hello world\n"; }); 

function< &foo::f_ptr >(); 

これはあなたが望むものをほぼ確実ではありません。

-1

のようなものテンプレートの種類を実装する

編集
はパラメータではなく、値として形を取ることはありません。この値は、テンプレートをインスタンス化するために実行時に決定可能である必要があり、ラムダの値はコンパイル時定数ではないので、このメソッドはまったく役に立たない。

template<typename Func> 
void foo(Func&& f) 
{ 
    f(); 
} 

そして、あなたはクラステンプレートをしたいので、(質問、ないコメントでそのような情報を入れてください)、ここでのクラスの使用例です:関数にファンクタを送信する一般的な方法はある

#include <utility> 

template<typename Func> 
class MyClass 
{ 
public: 
    MyClass(Func&& f) : f(f) {} 
    void Run() { f(); } 
private: 
    Func f; 
}; 

template<typename Func> 
MyClass<Func> MakeMyClass(Func&& f) 
{ 
    return { std::forward<Func>(f) }; 
} 

int main() 
{ 
    auto x = MakeMyClass([](){}); 
    x.Run(); 
} 
関連する問題