2017-03-23 4 views
1

Ich versuche, ein Ausführungsmuster zu implementieren, das jede Funktion übernimmt und es mit seinen eigenen Bedingungen/Vorbereitungen ausführt. Unabhängig davon, dass dies eine nützliche Sache zu tun ist, funktioniert es einfach nicht. Es scheint, dass ich nicht auf die Template-Überladung der "Execute" -Funktion (aufgerufen in "main") zugreifen kann.C++ Vorlage Überladung Anruf

Konkret: Warum kann ich die überladene Template-Funktion von Execute nicht aufrufen?

Dies ist das volle Programm:

#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; 
} 

Hinweis: Visual Studio Marken

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

Die Compilation löscht den Fehler

"type 'int' unexpected" 

Vielen Dank an alle bereit zu helfen!

+1

Vorsicht: 'ret' von Wert in Ihr Lambda erfasst wird. Dies wird nicht kompiliert, weil Sie versuchen, es im Körper zuzuordnen, ohne dass das Lambda veränderbar ist, und würde sowieso nicht das tun, was Sie wollen. Mit Verweis aufnehmen mit '[&]'. – Quentin

+0

Danke, dass ich darauf hingewiesen habe, ich habe das gerade in genau diesem Moment getestet. :) – Oachkatzl

Antwort

1

ExampleExecutor::Execute überschreibt nicht TransparentFunctionWrapper::Execute, und es versteckt es im executor.Execute<int> Anruf.

Sie müssen explizit TransparentFunctionWrapper::Execute aufrufen, da es von ExampleExecutor::Execute ausgeblendet wird. Hier ist eine Art und Weise, dies zu tun:

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

live example on coliru

+0

vielen Dank! Kennen Sie eine Möglichkeit, den "Execute" über die Klasse "ExampleExecutor" verfügbar zu machen? Aufruf mit "executor.TransparentFunctionWrapper :: Execute " ist ziemlich unhandlich. : P – Oachkatzl

+0

@Oachkatzl: Sie könnten einen Wrapper ** mit einem anderen Namen ** * (z. B. "ExecuteBase") * in 'ExampleExecutor 'bereitstellen, der' TransparentFunctionWrapper :: Execute 'aufruft. –

+0

danke für deine antwort! Seltsamerweise, wenn ich die "Execute (function )" in "ExecuteWithReturn" umbenenne, verbirgt das "ExampleExecutor" es nicht. Das befriedigt mich nicht wirklich, da ich es überladen wollte, um klar zu machen, dass sie im Grunde dasselbe machen, aber ich denke, das ist so gut, wie es wird. – Oachkatzl

Verwandte Themen