2017-03-23 3 views
1

私は任意の関数をとり、それ自身の条件/準備で実行する実行パターンを実装しようとしています。これが有用なものであることを問わず、それは機能しません。それは私が "実行"機能( "メイン"と呼ばれる)のテンプレートの過負荷にアクセスすることはできないようです。C++テンプレートのオーバーロードコール

具体的には:なぜ、実行のオーバーロードされたテンプレート関数を呼び出せないのですか?

これは完全なプログラムです:

#include "stdafx.h" 
#include <functional> 

class TransparentFunctionWrapper 
{ 
public: 
    virtual void Execute(std::function<void()> executeFunction) = 0; 

    template<class C> 
    C Execute(std::function<C(void)> executeFunction) // template-overload of the abstract function which will implicitly call it 
    { 
     C ret; 
     Execute(// calls the abstract function with a lambda function as parameter 
     [ret, executeFunction](void) -> C  // lambda declaraction 
     {          // 
      ret = executeFunction;    // lambda body 
     });          // 
     return ret; 
    } 
}; 

class ExampleExecutor : public TransparentFunctionWrapper 
{ 
public: 
    virtual void Execute(std::function<void()> executeFunction) 
    { 
     printf("executed before."); 
     executeFunction(); 
     printf("executed after."); 
    } 
}; 

void DoStuff() {} 
int ReturnStuff() { return -5; } 

int main() 
{ 
    ExampleExecutor executor; 

    executor.Execute(DoStuff); 
    int i = executor.Execute<int>(ReturnStuff);  // Why does this not work? ERROR: "type name is not allowed" 

    getchar(); 
    return 0; 
} 

注:Visual Studioのマーク

Execute<int>(ReturnStuff) // "int" is marked as Error: type name is not allowed 

コンパイルエラー

"type 'int' unexpected" 

助けて喜んでみんなに感謝を出して!

+1

注意: 'ret'があなたのラムダに値によって捕獲されます。これはコンパイルできません。ラムダが変更可能でなく本体に割り当てようとしているからです。とにかくあなたが望むことはしません。 '[&]'で参照することでキャプチャします。 – Quentin

+0

これを指摘してくれてありがとう、私は実際にこの時点でこれを実際にデバッグしていました。 :) – Oachkatzl

答えて

1

ExampleExecutor::Executeは、TransparentFunctionWrapper::Executeを無効にしておらず、executor.Execute<int>コールで非表示になっています。

ExampleExecutor::Executeによって隠されているため、TransparentFunctionWrapper::Executeを明示的に呼び出す必要があります。ここではそれを行うの可能な方法があります:

int i = executor.TransparentFunctionWrapper::Execute<int>(ReturnStuff); 

live example on coliru

+0

ありがとうございます! "Execute"を "ExampleExecutor"クラスを通して公開する方法を知っていますか? "executor.TransparentFunctionWrapper :: Execute "で呼び出すのはむしろ不自由です。 :P – Oachkatzl

+0

@Oachkatzl: 'TransparentFunctionWrapper :: Execute'を呼び出す' ExampleExecutor'内の別の名前** *(例えば 'ExecuteBase')*でラッパー**を提供することができます。あなたの答えは –

+0

ありがとう!不思議なことに、「Execute(function )」の名前を「ExecuteWithReturn」に変更すると、「ExampleExecutor」はそれを非表示にしません。基本的には同じことをしていることを明確にするために過負荷をかけたいと思っていたので、これは私を満足させるものではありませんが、それが得られるほど良いと思います。 – Oachkatzl