2017-11-16 12 views
3

は、この擬似スニペットを考えてみましょクラスのメンバとして一般的なのstd ::機能を備えた一般的なラムダは:C++ 14:

class SomeClass 
{ 
public: 
    SomeClass() 
    { 
     if(true) 
     { 
      fooCall = [](auto a){ cout << a.sayHello(); }; 
     } 
     else 
     { 
      fooCall = [](auto b){ cout << b.sayHello(); }; 
     } 
    } 
private: 
    template<typename T> 
    std::function<void(T)> fooCall; 
}; 

私が欲しいのは順番にある一般的なラムダを、保存するクラスのメンバーfooCallですコンストラクタで割り当てられます。

fooCallはテンプレート化されたデータメンバーではありません。

クラスに汎用ラムダを保存する方法は簡単ですか?

+1

残念ながら、単純な解決策はありません。一般的なラムダは、テンプレート化された関数のように考えてください。まだインスタンス化されていないため、アドレスを取得できません。具体的なユースケースについてもっと知る必要があります。おそらく、小さなワークフローでOPを完成させることができますか? – AndyG

+0

あなたが解決しようとしている実際の問題は何ですか? – Barry

+0

クラスのメンバとしてジェネリックラムダを格納できませんでしたが、クラスのコンストラクタ内でコールを呼び出すことができました。 –

答えて

2

タイプイレーズの具体的な署名がないため、実行時に2つの汎用ラムダを選択する方法はありません。

あなたはコンパイル時に決定をすることができる場合は、クラス自体をテンプレート化することができます

template <typename F> 
class SomeClass 
{ 
private: 
    F fooCall; 

public: 
    SomeClass(F&& f) : fooCall{std::move(f)} { } 
}; 

あなたはその後、Fを推定するヘルパー関数を作成することができます。

auto makeSomeClassImpl(std::true_type) 
{ 
    auto l = [](auto a){ cout << a.sayHello(); }; 
    return SomeClass<decltype(l)>{std::move(l)}; 
} 

auto makeSomeClassImpl(std::false_type) 
{ 
    auto l = [](auto b){ cout << b.sayHello(); }; 
    return SomeClass<decltype(l)>{std::move(l)}; 
} 

template <bool B> 
auto makeSomeClass() 
{ 
    return makeSomeClassImpl(std::bool_constant<B>{}); 
} 
+0

Thxですが、条件は実行時にのみ利用可能です:-( – juxeii

+0

@juxeii:それを反映するようにOPを更新してください。動作させるには、何らかの形式の消去を行う必要があります。 – AndyG

1

私はしませんでしたクラス内にstd::function<>generic lambdaとして直接格納することができます。memberです。私ができることは、クラスのコンストラクタ内で具体的に使用することでした。私はこれがOPの達成しようとしていたものであれば100%確信していませんが、これは私がコンパイルできたもので、OP32が提供したコードでOPが疑わしいと思っているものを実行してください。上記の適切なヘッダを持つ

template<class> 
class test { 
public: // While testing I changed this to public access... 
     // Could not get object below to compile, build & run 
    /*template<class U = T> 
    static std::function<void(U)> fooCall;*/ 
public: 
    test(); 
}; 

template<class T> 
test<T>::test() { 
    // This would not compile, build & run 
    // fooCall<T> = [](T t) { std::cout << t.sayHello(); }; 

    // Removed the variable within the class as a member and moved it here 
    // to local scope of the class's constructor 
    std::function<void(T)> fooCall = [](auto a) { std::cout << a.sayHello(); }; 
    T t; // created an instance of <Type T> 
    fooCall(t); // passed t into fooCall's constructor to invoke the call. 
} 

struct A { 
    std::string sayHello() { return "A say's Hello!\n"; } 
}; 

struct B { 
    std::string sayHello() { return "B say's Hello!\n"; } 
}; 


int main() { 
    // could not instantiate an object of SomeClass<T> with a member of 
    // a std::function<> type that is stored by a type of a generic lambda. 

    /*SomeClass<A> someA; 
    SomeClass<B> someB; 
    someA.foo(); 
    someB.foo();*/ 

    // Simply just used the object's constructors to invoke the locally stored lambda within the class's constructor. 
    test<A> a; 
    test<B> b; 

    std::cout << "\nPress any key & enter to quit." << std::endl; 
    char c; 
    std::cin >> c; 

    return 0; 
} 

以下の出力を与える&実行を構築し、コンパイルする必要がありますされるよう(Windows 7の64ビット版に少なくともMSVS 2017年にやりました)。私はエラーに遭遇した箇所にコメントを残し、実例を達成するために複数の異なるテクニックを試しました。他の人たちが示唆するようにエラーが発生し、上記のコードで作業していました。私がコンパイル、ビルド、実行することができたのは、この単純なコードをコメントなしでここに集めました。私はまた、それがどのようなタイプで動作します表示するには、別の単純なクラスを追加しました:

template<class> 
class test { 
public: 
    test(); 
}; 

template<class T> 
test<T>::test() { 
    std::function<void(T)> fooCall = [](auto a) { std::cout << a.sayHello(); }; 
    T t; 
    fooCall(t); 
} 

struct A { 
    std::string sayHello() { return "A say's Hello!\n"; } 
}; 

struct B { 
    std::string sayHello() { return "B say's Hello!\n"; } 
}; 

struct C {  
    int sayHello() { return 100; } 
}; 

int main() { 
    test<A> testA; 
    test<B> testB; 
    test<C> testC; 

    std::cout << "\nPress any key & enter to quit." << std::endl; 
    char c; 
    std::cin >> c; 

    return 0; 
} 

出力:

A say's Hello! 
B say's Hello! 
100 

Press any key & enter to quit 

これは、直接または間接的にか、それならばOPを助ける場合、私は知りませんそうでない場合でも、それはまだ彼らが戻って来るかもしれない何かである。

関連する問題