2016-02-10 10 views
6

Beim Kompilieren Sie den folgenden Code:Kann nicht nennen generic std :: function Mitglied von Template-Klasse

#include <functional> 

template <typename functionSignature> 
class Class 
{   
    std::function<functionSignature> func; 
public: 
    Class(const std::function<functionSignature>& arg) : func(arg) {} 
    void callFunc() { func(); } 
}; 

void f(const int i) {} 

int main() 
{ 
    Class<void(const int)> a(std::bind(f, 10)); 
    a.callFunc(); 
    return 0; 
} 

Der VS 2015-Compiler generiert die folgende Fehlermeldung bei der sechsten Zeile:

error C2064: term does not evaluate to a function taking 0 arguments. 

Jetzt, Ich glaube, das ist, weil der Compiler denkt, functionSignature ist nicht, nun, eine Funktionssignatur; Derselbe Fehler tritt auf, wenn ich zum Beispiel operator() auf einem std::function<int> anstelle von std::function<int()> instanziiere und versuche, ihn aufzurufen.

Wie kann ich garantieren, dass das Template-Argument immer eine Funktionssignatur ist, so dass ich operator() auf dem std::function anrufen kann?

+0

Können Sie bitte den Code genau aktualisieren, wie Sie Ihre Klasse aufrufen und wie Sie Ihre Klasse initialisieren? – Jts

+0

Ja, ein tatsächlicher MCVE würde helfen. Fügen Sie einfach ein Spielzeug 'main' hinzu, das eine Instanz Ihrer' Class > dann '' callFunc() 'darauf, und bestätigen Sie, dass es kompiliert und den Fehler in MSVC generiert. – Yakk

Antwort

2

Ihr Fehler ist hier:

Class<void(const int)> a(std::bind(f, 10)); 

Die Funktion Class::callFunc() ruft func() - das heißt, keine Argumente. Das Ergebnis von std::bind(f, 10) ist auch eine Funktion, die keine Argumente akzeptiert, was mit dem Template-Argument der Klassenvorlage übereinstimmt. Die Verwendung von widerspricht sowohl der Verwendung in der Klassenvorlage als auch der Initialisierung.

Die Lösung ist einfach: Ändern Sie die fehlerhafte Zeile

Class<void()> a(std::bind(f, 10)); 
+0

Nun, da das OP die ursprüngliche Frage geändert hat, macht meine erste Antwort noch Sinn, aber diese ist in der Tat mehr konzentriert. – skypjack

+1

@skypjack - Es gab nicht viel zu dem Zeitpunkt, zu dem du deine Antwort geschrieben hast. Sie lesen die Meinung des OP und dann einige. +1, auf deine Antwort, das ist. –

6

Ich vermute, Sie so etwas wollen:

template <typename F> 
class Class; 

template<typename R, typename... P> 
class Class<R(P...)> { 
public: 
    std::function<R(P...)> func; 
    void callFunc(P... p) { func(p...); } 
}; 

Durch die Verwendung von teilweise Spezialisierung auf diese Weise Sie einfach den Typ definieren können Sie wollen.

Class<int(double)> c; 

Natürlich habe ich bemerkt, dass Sie für Ihre Klasse keine Konstrukteure haben, so func ist keine gute Idee, berufen, aber es ist ganz einfach, es zu definieren:
Als Beispiel können Sie es als verwenden und übergeben Sie eine ordnungsgemäße Funktion als Argument.

Es folgt eine vollständige und Arbeitsbeispiel, wo ich die operator() verwendet habe, um die Funktion aufzurufen:

#include <functional> 

template <typename F> 
class Class; 

template<typename R, typename... P> 
class Class<R(P...)> { 
public: 
    Class(std::function<R(P...)> f): func{f} { } 
    void operator()(P... p) { func(p...); } 
private: 
    std::function<R(P...)> func; 
}; 

void fn() { } 

int main() { 
    std::function<void()> f = fn; 
    Class<void()> c{f}; 
    c(); 
} 
+0

+1, Dies beantwortete die Frage, für die ich gegoogelt hatte und die, von der ich dachte, dass es sich um den Titel der Frage handelte. – AnorZaken

1

Ist das, was Sie zu tun versuchen?

http://ideone.com/fork/IZ0Z1A

Wenn functionSignature keine Funktion, std ist :: Funktion Fehler auswerfen, wenn Sie Klasse erstellen, aber Sie können einen Konstruktor hinzufügen und ein static_assert(std::is_function<functionSignature>::value == true," "); werfen, wenn Sie wollen, denke ich.

#include <functional> 
#include <iostream> 

template <typename functionSignature> 
class Class 
{ 
public: 
    std::function<functionSignature> func; 
    void callFunc() { func(); } 
}; 

void f() 
{ 
    std::cout << "hello" << std::endl; 
} 

int main() 
{ 
    Class<decltype(f)> t {f}; 
    t.callFunc(); 

    return 0; 
} 
Verwandte Themen