2017-12-06 7 views
0

Ich versuche, herauszufinden, wie ich eine Template-Klasse zu machen, die wie folgt funktioniert:Wie können Sie eine Funktion als Template-Parameter übergeben, in der die Rückgabe der Funktion dem Template-Parameter entspricht?

template<typename T, typename Fn> 
class Point 
{ 
public: 
    T x; 
    T y; 

    void pt(const std::string& x_str, const std::string& y_str) 
    { 
      x = Fn(x_str); 
      y = Fn(y_str); 
    } 
    .... more Point stuff .... 
}; 

typedef Point<float, std::stof> FPoint; 
typedef Point<int, std::stoi> IPoint; 
..... 

und dann, wenn ich einen String gelesen - sagen: „100.25,200.25“, konnte ich gespalten auf „“ (was ich aus eigentlich dachte, wie zu tun, und dann sagen, stellen Sie diesen Punkt:

FPoint a; 
a.pt("100.25","200.25") 

bisher habe ich versucht, die Definition direkt wie ich oben habe, habe ich versucht:

template<typename T, T (C*)(const std::string&)> 
..... 

und

template<typename T, T Fn(const std::string&)> 
...... 

und dann tun: typedef Punkt FloatPoint;

und ich bekomme verschiedene Fehler wie kann nicht von 'overloaded-Funktion' in 'float (__cdecl *) konvertieren (const std :: string &)' oder 'std :: stof' ist kein gültiges Template-Typ-Argument für Parameter 'convert_func' abhängig davon, wie ich den Parameter definieren möchte. Irgendwelche Hinweise - nichts, was ich gegoogelt habe, schien mir zu helfen.

Danke!

Antwort

1

können Sie nicht

typedef Point<float, std::stof> FPoint; 

seit std::stof verwenden ein Zeiger auf eine Funktion, kein Typ.

Sie könnten versuchen, die Template-Parameter auf einen Nicht-Typ-Parameter zu ändern, wie zum Beispiel:

template<typename T, T(*Fn)(const std::string&)> 
class Point { ... }; 

aber das wird nicht funktionieren, da std::stof einen optionalen Parameter des Typs std::size_t* hat. Der Typ std::stof, der als erster Parameter std::string const& verwendet, ist float (*)(std::string const&, std::size_t*).

Wenn Sie versuchen, Point Schuhanzieher diese Erklärung zu entsprechen,

template<typename T, T(*Fn)(const std::string&, std::size_t*)> 
class Point { ... }; 

Sie nicht zu verwenden in der Lage:

typedef Point<int, std::stoi> IPoint; 

seit std::stoi einen dritten Parameter, int base. Der Typ std::stoi ist int (*)(std::string const&, std::size_t*, int).

Ich denke, Ihre beste Option besteht darin, zwei Wrapper-Funktionen in Ihrem Namespace zu erstellen und sie anstelle von std::stof und std::stoi direkt als Vorlageparameter zu verwenden.

Das folgende demonstrative Programm funktioniert in meinem Setup.

#include <cstdlib> 
#include <string> 
#include <functional> 

template<typename T, T(*Fn)(const std::string&)> 
class Point 
{ 
public: 
    T x; 
    T y; 

    void pt(const std::string& x_str, const std::string& y_str) 
    { 
     x = Fn(x_str); 
     y = Fn(y_str); 
    } 
}; 

namespace MyApp 
{ 
    float stof(std::string const& in) 
    { 
     return std::stof(in); 
    } 

    int stoi(std::string const& in) 
    { 
     return std::stoi(in); 
    } 
} 

typedef Point<float, MyApp::stof> FPoint; 
typedef Point<int, MyApp::stoi> IPoint; 

int main() 
{ 
    FPoint a; 
    a.pt("100.25", "200.25"); 
    IPoint b; 
    b.pt("100", "200"); 
} 
0

Ich denke, ich habe es herausgefunden - std :: stof ist eigentlich std :: stof (const string &, size_t *). Ich stelle das in den Template-Parameter (T (C *) (const std :: string &, size_t *) und erhalte jetzt Fehler in den Stimulationen, in denen ich Point als nicht genug Parameter benutze. Nachdem ich das behoben habe, wenn ich es bin immer noch falsch, komme ich zurück und entfernen Sie diese Antwort

+0

Yup - das war es .... offenbar, weil es auf Vorlagen ist, ich habe alle Parmeters verwenden, auch wenn std :: stof als std :: stof (const std :: string &, size_t definiert ist * = 0) – tenspd137

0

der zweite Parameter Machen Sie einen Funktionszeiger sein. Vorlage class Point {};

Beachten Sie, dass weder std :: stof oder std :: Stoi wären gültige Argumente für diese Vorlage (sie nehmen beide zusätzliche Argumente an), aber es wäre ziemlich einfach Wrapper zu erstellen, die auf den Standardparametern basieren (das Template-Argument muss Typen genau entsprechen, während der Aufruf nicht): typed ef Punkt fPoint;

Verwandte Themen