Template-Spezialisierung Problem



  • Hallo,

    Ich habe folgenden Code:

    template < typename T0,typename T1 > T0 lexical_cast (T1 p_source) {
    	T0 buffer;
    	stringstream ss;
    	ss << p_source;
    	ss >> buffer;
    	return buffer;
    };
    template < typename T1 > char * lexical_cast < char *,T1 > (T1 p_source) {
    	stringstream ss;
    	ss << p_source;
    	return & ss.str () [0];
    };
    template < typename T1 > char const * lexical_cast < char const *,T1 > (T1 p_source) {
    	stringstream ss;
    	ss << p_source;
    	return & ss.str () [0];
    };
    unsigned int counter = 10;
    const char * test = lexical_cast < const char * > (counter);
    

    Ich bekomme folgende Fehler:

    C:\Program Files (x86)\MinGW/PHBU.hpp:48:72: error: function template partial specialization 'lexical_cast<char *, T1>' is not allowed
    C:\Program Files (x86)\MinGW/PHBU.hpp:53:84: error: function template partial specialization 'lexical_cast<const char *, T1>' is not allowed

    Wieso ist die Spezialisierung nicht erlaubt bzw. wie müsste der Code richtig aussehen?

    Danke im Voraus!

    MfG

    Seikuassi



  • Funktionen können nicht spezialisiert werden, sondern nur überladen.

    Die mechanische Transformation ist, die Funktionen in structs umzuwandeln und diese zu spezialisieren. Hier gibt jedoch eine schönere Lösung:

    template <typename T> struct result_tag {};
    
    template <typename T0, typename T1>
    T0 lexical_cast_(result_tag<T0>, T1 p_source) {
      T0 buffer;
      stringstream ss;
      ss << p_source;
      ss >> buffer;
      return buffer;
    }
    
    template <typename T1> char *lexical_cast_(result_tag<char *>, T1 p_source) {
      stringstream ss;
      ss << p_source;
      return &ss.str()[0];
    }
    
    template <typename T1>
    char const *lexical_cast_(result_tag<char const *>, T1 p_source) {
      stringstream ss;
      ss << p_source;
      return &ss.str()[0];
    }
    
    template <typename T0, typename T1> T0 lexical_cast(T1 p_source) {
      return lexical_cast(result_tag<T0>{}, p_source);
    }
    

    Dass dein Code sehr ineffizient ist, weil du alles per value übergibst dürfte dir hoffentlich bewusst sein.



  • Gibt es einen Grund, wieso du boost::lexical_cast neu erfindest?

    P.S.: Hätten wir bloß static if ... 🤡



  • Hallo nochmal,

    Gibt es einen Grund, wieso du boost::lexical_cast neu erfindest?

    Bestimmt...mir fällt nur gerade keiner ein 😃 .

    So müsste doch die Funktion/en auch ohne struct gehen, oder?

    template < typename T0 > T0 lexical_cast (char * p_var) {
    	T0 buffer;
    	stringstream ss;
    	ss << p_var;
    	ss >> buffer;
    	return buffer;
    };
    template < typename T0 > T0 lexical_cast (char const * p_var) {
    	T0 buffer;
    	stringstream ss;
    	ss << p_var;
    	ss >> buffer;
    	return buffer;
    };
    template < typename T1,typename T0 > T1 lexical_cast (T0 p_var) {
    	stringstream ss;
    	ss << p_var;
    	return & ss.str () [0];
    };
    

    Zwar immer noch ineffizient, aber funktionstüchtig.

    Müsste ich eigentlich wissen 🙄 : Das ist nur eine Überladung, keine Spezialisierung, oder?

    MfG

    Seikuassi


  • Mod

    Niemand stört sich an

    return &ss.str()[0];
    

    ?



  • camper schrieb:

    Niemand stört sich an

    return &ss.str()[0];
    

    ?

    Edit: Beziehst du dich gerade auf den neuesten Code-Schnipsel? Da ist es sowieso Blödsinn, aber ich dachte, auf solche offensichtlichen Kleinigkeiten würdest du nicht hinweisen, das ist doch unter deinem Niveau...

    Das ist nur eine Überladung, keine Spezialisierung, oder?

    Richtig.



  • camper schrieb:

    Niemand stört sich an

    return &ss.str()[0];
    

    ?

    So genau habe ich mir den Code gar nicht angeschaut. Aber stimmt schon, ein Lexical-Cast nach const char* und char* ist prinzipiell gar nicht vernünftig umzusetzen.



  • Natürlich, du meintest den ersten...

    Und damit hat overloard Recht, das kann man tatsächlich nicht richtig umsetzen. Eine unschöne Möglichkeit wäre, den Zeiger in einem statischen Zeiger-Array zu speichern, welches per at_exit geleert wird (Edit: Das geht natürlich auch direkter, mit einem std::string o.ä.). Das sollte funktionieren.



  • Sone schrieb:

    Eine unschöne Möglichkeit wäre, den Zeiger in einem statischen Zeiger-Array zu speichern, welches per at_exit geleert wird. Das sollte funktionieren.

    Inwiefern ist das besser als ein Memory-Leak? (War eine rhetorische Frage: Es ist genauso schlecht, nur langsamer)

    Und ich habe gesagt:

    overloard schrieb:

    nicht vernünftig



  • overloard schrieb:

    Sone schrieb:

    Eine unschöne Möglichkeit wäre, den Zeiger in einem statischen Zeiger-Array zu speichern, welches per at_exit geleert wird. Das sollte funktionieren.

    Inwiefern ist das besser als ein Memory-Leak? (War eine rhetorische Frage: Es ist genauso schlecht, nur langsamer)

    Weil das Betriebssystem es sowieso aufräumt... nun gut, es gibt keine richtige Möglichkeit.

    Aber: Man kann einen Zeiger nehmen. Das wäre hier der beste Lösungsweg.

    Und ich habe gesagt:

    overloard schrieb:

    nicht vernünftig

    Genau darauf bezog ich mich ja auch, es ist nicht richtig lösbar, also vernünftig. Eine unschöne Möglichkeit schlug ich vor, die eben unschön ist. 🙂



  • total nervig Sone ändert ständig den text seiner beiträge


Anmelden zum Antworten