2017-03-23 1 views
1

J'essaye d'implémenter un modèle d'exécution qui prend n'importe quelle fonction et l'exécute avec ses propres conditions/préparations. Indépendamment de ce qui est une chose utile à faire, cela ne fonctionne tout simplement pas. Il semble que je ne puisse pas accéder à la surcharge du template de la fonction "Execute" (appelée dans "main").Appel de surcharge de template C++

Spécifiquement: Pourquoi ne puis-je pas appeler la fonction de modèle surchargé de Execute?

Voici le programme complet:

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

Note: les marques Visual Studio

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

La compilation met l'erreur

"type 'int' unexpected" 

Merci à tout le monde prêt à vous aider!

+1

Attention: 'ret' est capturé par la valeur dans votre lambda. Cela ne compilera pas parce que vous essayez de l'assigner dans le corps sans que le lambda ne soit mutable, et ne ferais pas ce que vous voulez de toute façon. Capture par référence avec '[&]'. – Quentin

+0

merci de m'avoir fait remarquer, je débuggeais cela exactement dans ce moment. :) – Oachkatzl

Répondre

1

ExampleExecutor::Execute ne surcharge pas TransparentFunctionWrapper::Execute et il le masque dans l'appel executor.Execute<int>.

Vous devez explicitement appeler TransparentFunctionWrapper::Execute, car il est masqué par ExampleExecutor::Execute. Voici un moyen possible de le faire:

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

live example on coliru

+0

merci beaucoup! connaissez-vous un moyen d'exposer le "Execute" à travers la classe "ExampleExecutor"? l'appeler avec "executor.TransparentFunctionWrapper :: Execute " est plutôt difficile. : P – Oachkatzl

+0

@Oakkatzl: vous pouvez fournir un wrapper ** avec un nom différent ** * (par exemple 'ExecuteBase') * dans' ExampleExecutor' qui appelle 'TransparentFunctionWrapper :: Execute'. –

+0

merci pour votre réponse! Curieusement, si je renommer le "Execute (fonction )" en "ExecuteWithReturn" le "ExampleExecutor" ne le cache pas. Cela ne me satisfait pas vraiment car je voulais le surcharger pour qu'il soit clair qu'ils font essentiellement la même chose mais je suppose que c'est aussi bon que ça va l'être. – Oachkatzl