2009-05-20 20 views
1

Ich versuche, eine generische toString() - Funktion zu implementieren, die auf allen Typen funktionieren würde. Alle unsere internen Klassen stammen von Abstract, das eine Signatur für toString() enthält. Mit anderen Worten, alle unsere internen Klassen haben in irgendeiner Form eine toString-Methode.C++ Vorlage Spezialisierung Frage

Das Problem ist, die primitiven Typen (int, char, double ..) haben keine native toString-Funktion. Aber wir haben eine Dienstprogrammfunktion, die lexical_cast aufruft, um den Zeichenfolgenwert des Grundelements zurückzugeben. Wir wollen nicht eine ganze Menge von if-Anweisungen abhängig. Also versuche ich, eine templated Utility-Klasse zu erstellen, die diese Aufgabe übernehmen würde.

Mein erster Hack auf das ist die folgende Liste:

template<class T> 
    class ObjectToString { 
    public: 
     string objectToString(T value) { 
      iil::stringUtils::StringSp ret(stringUtils::valueToString<T>(value)); 
      return ret; 
     } 
    }; 

    template<> 
    class ObjectToString <Abstract<T>*> { 
    public: 
     iil::stringUtils::StringSp objectToString(Abstract<T>* value) { 
      return iil::stringUtils::StringSp(new std::string("AAAA")); 
     } 
    }; 

Das Problem ist jetzt, da Zusammenfassung eine Templat-Klasse ist, muss er die Vorlage Wert T. Ich habe keine Ahnung, wie das setzen. Könnte jemand beraten?

+1

klingt wie Sie Java implementieren –

Antwort

2

Ist das Problem nicht viel einfacher? Auf allen Abstrakte Objekte wissen Sie, was zu tun ist, um alles, was Sie brauchen, ist überladene Funktionen für integrierte Typen zur Verfügung zu stellen:

string getAsString(Abstract *obj) 
{ 
    return obj->toString(); 
} 

string getAsString(int x) 
{ 
    return intToStr(x); 
} 

string getAsString(double x) 
{ 
    return doubleToStr(x); 
} 

etc, wo Sie implementieren IntToStr() und doubleToStr() als angemessen.

8

Wie wäre es mit einer einfachen Spezialisierung für lexical_cast?

template<> string lexical_cast(Abstract* obj) 
{ 
    return obj->toString(); 
} 
1

Sie denken einfach nicht in C++ Weise. C++ bereits hat "toString", das heißt operator<< bis std::ostream. Sie müssen es für Ihre Klassen implementieren.

Und wenn Sie inheritence unterstützen wollen, dies zu tun:

#include <iostream> 
#include <boost/lexical_cast.hpp> 
#include <string> 

class streamable { 
public: 
    virtual void stream(std::ostream &) const = 0; 
}; 
std::ostream &operator<<(std::ostream &out,streamable const &obj) 
{ 
    obj.stream(out); 
    return out; 
} 

// Now anything derived from streamable can be written to std::ostream 
// For example: 

class bar : public streamable { 
    int x; 
    int y; 
public: 
    bar(int a,int b) : x(a),y(b){} 
    virtual void stream(std::ostream &out) const { out<<x<<":"<<y; } 
}; 

int main() 
{ 
    bar b(1,3); 
    std::cout<< b << std::endl; 

    // and converted to string 
    std::string str=boost::lexical_cast<std::string>(b); 

    std::cout<< str <<std::endl; 
} 

Diese ist C++ Art und Weise, und wie Sie Sie haben boost::lexical_cast kostenlos sehen können.

EDIT für Ihren Fall:

template<typename T> 
class Abstract { 
public: 
    virtual void stream(std::ostream &) const = 0; 
}; 

template<typename T> 
std::ostream &operator<<(std::ostream &out,Abstract<T> const &obj) 
{ 
    obj.stream(out); 
    return out; 
} 

Nun, wenn Sie nicht boost :: lexical_cast gefällt, implementieren string_cast so einfach wie

template<typename T> 
std::string string_cast(T const &obj) 
{ 
    std::ostringstram ss; 
    ss<<obj; 
    return ss.str(); 
} 
Verwandte Themen