2016-10-16 11 views
3

In C++ ist möglich, so etwas zu machen:C++ Template-Parameter als Funktionsaufruf Name

class A 
{ 
public: 
    template <typename ClassType, typename MethodName, typename ...Args> 
    static func() 
    { 
     ClassType t = GetPtr<ClassType>(); 
     t->MethodName(GetArg<Args>()...); 
    } 
} 

A::func<B, sum, double, double>(); //should call B->sum(double, double) 
A::func<C, sum2, std::string, double, double>(); //should call C->sum2(std::string, double, double) 

wo GetPtr und GetArgs arbeiten Methoden Zeiger von Wörterbuch zu erhalten.

+1

Wo haben Sie vor, Argumente für 'MethodName' aufzurufen? –

+0

@EdgarRokyan Es sind von Lua übergeben. Jeder 'GetArg 'ruft ein Argument vom Stack auf. Ich habe Vorlagen Spezialisierungsmethoden für verschiedene 'T' –

+1

MethodName ist ein Typ. Aus der Sicht der Dinge benötigen Sie einen Mitgliedsfunktionszeiger. Vorlagenvorlage vielleicht? – DeiDei

Antwort

3

Sie könnten die Verwendung von nicht-Typ Template-Parameter machen wie:

template <typename ClassType, typename MethodType, MethodType MethodName, typename ...Args> 
static void func() { 
    ClassType t = GetPtr<ClassType>(); 
    (t->*MethodName)(GetArg<Args>()...); 
} 

es wie folgt zu verwenden:

A::func<B, double (B::*)(double,double), &B::sum, double, double>(); 

Wenn Ihr Compiler C++ 17 Code unterstützen auch bekommen könnte verkürzt:

template <typename ClassType, auto MethodName, typename ...Args> 
static void func() { 
    ClassType t = GetPtr<ClassType>(); 
    (t->*MethodName)(GetArg<Args>()...); 
} 

Mit Nutzung:

A::func<B, &B::sum, double, double>(); 
+0

Ich bekomme ''MethodName': ist kein Mitglied von 'B'' (Ich habe' Klasse B {public: double sum (double a, double b) {return a + b;}} ') –

+0

erstellt, sorry Tippfehler - machen bearbeiten –

+0

@MartinPerry versuchen Sie dieses –

1

nicht genau das, was Sie aufgefordert, aber ich nehme an, Sie someting wie

#include <array> 
#include <vector> 
#include <iostream> 

template <typename Class, typename Method, typename ... Args> 
void callMethod (Class & c, Method m, Args ... args) 
{ ((&c)->*m)(args...); } 

int main() 
{ 
    std::vector<int>  v; 
    std::array<int, 5U> a; 

    callMethod(v, &std::vector<int>::size); 
    callMethod(v, static_cast<void (std::vector<int>::*)(int const &)> 
        (&std::vector<int>::push_back), 7); 
    callMethod(a, &std::array<int, 5U>::fill, 3); 

    std::cout << v.back() << std::endl; // print "7" 

    for (auto const i : a) 
     std::cout << i << std::endl; // print "3" five times 
} 

Beachten Sie, dass mit push_back() Methode von std::vector<int> tun können, müssen Sie eine Besetzung (static_cast<void (std::vector<int>::*)(int const &)>), um die Überlastung Mehrdeutigkeit aufzulösen (es gibt zwei push_back() in std::vector<int>)

nicht über die Verwendung von GetPtr() sicher und GetArgs(), aber ich nehme an, Sie callMethod() wie folgt

verwenden können
callMethod(GetPtr<B>(), &B::sum, GetArgs<double>(), 
      GetArgs<double>()); 
callMethod(GetPtr<C>(), &C::sum2, GetArgs<std::string>(), 
      GetArgs<double>(), GetArgs<double>()); 
1

wie das Wort typename schon sagt, nein, das wird nicht funktionieren (in der Regel), aber:

Sie können im Grunde nur eine Klasse erstellen, die operator(.) Überlastungen, und tut, um die Berufung in dem überladenen Operator.

In der Tat, Boost::bind macht genau das und ermöglicht es Ihnen, "Funktor" -Objekte zu erhalten, die Sie zur Laufzeit als Objekte weitergeben können.

Verwandte Themen