Direkte Anweisung an Compiler welcher Konstruktor genutzt werden soll möglich?



  • Hallo,

    ich habe derzeit ein Problem mit folgender Stringklasse (gekürzt):

    class RString : public std::string
    public:
    	RString(const char *szText);
    	RString(const char *szFormat, ...);
    
    	/* weitere Methoden */
    

    Diese beiden Konstruktoren funktionieren beim Erzeugen der Objekte via Zuweisungsoperator problemlos. Jetzt möchte ich aber folgendes durchführen:

    const char *szText = "Hallo Welt";
    auto paired = std::pair<RString, int> (szText, 3)
    

    Dabei erhalte ich von Visual Studio folgenden Fehler:

    error C2668: 'RString::RString' : ambiguous call to overloaded function
    

    mit Verweis auf meine beiden Konstruktoren. Dies ist für mich in soweit verständlich, da "..." auch "0 weitere Argumente" bedeuten kann. Jetzt stellt sich für mich die Frage, wie ich dieses Problem am besten umgehen kann.
    Kann ich den Compiler irgendwie direkt anweisen den ersten Konstruktor zu nutzen?

    Grüße
    int128_t



  • Ach, du heilige Scheiße.

    Zunächst mal solltest du von std::string nicht (öffentlich) erben; std::string ist nicht auf Polymorphie ausgelegt (hat keinen virtuellen Destruktor). Es gibt die gleichen Probleme wie bei allen anderen Standardcontainern. Mach das mit Komposition, so dass RString einen std::string besitzt, aber keiner ist. Wenn es dir nur darum geht, das Interface zu erweitern, benutz freie Funktionen. Damit löst sich auch das Problem auf, weil du die einfach unterschiedlich nennen kannst.

    Aber auch der Rest des Vorhabens ist zweifelhaft. Ellipsen? Du schreibst hier kein C! Du willst auf alle Fälle Typsicherheit herstellen, und das ist dir auf diese Weise nicht möglich - zumal du so auf die Typen beschränkt wärst, die RString zu formatieren versteht. Hattest du etwa vor, das hinterher in vsprintf zu werfen?

    Die Antwort auf deine Wünsche dürfte Boost.Format sein.



  • Warum überhaupt 2 Konstruktoren? Kenne mich mit den Formatstrings nicht so gut aus, aber das sollte man doch auch in einen packen können.



  • Der Tobi schrieb:

    Warum überhaupt 2 Konstruktoren? Kenne mich mit den Formatstrings nicht so gut aus, aber das sollte man doch auch in einen packen können.

    👍
    Eigentlich ist es so gedacht das man dann einen einfachen String übergeben kann in dem man die zusätzlichen Argumente einfach weglässt. Also sollte man auch den ersten Ctor einfach weglassen können, weil der zweite bei einem einfachen String eh das gleiche tun sollte.



  • Sone schrieb:

    Also sollte man auch den ersten Ctor einfach weglassen können, weil der zweite bei einem einfachen String eh das gleiche tun sollte.

    👎
    Beispiel RString("%s") . printf ist überigens auch nicht dafür da ohne Argument aufgerufen zu werden, dafür gibt es puts , das ist sicherer.

    @TE: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Named_Constructor
    Also mach etwas in der Art:

    class RString {
        std::string data;
    public:
        RString(const char *text) : data (text) {}
    
        static RString format(const char *format, ...)
        { char buf[1024]; /* fülle buf mit vsprintf */ return RString(buf); }
    
        /* weitere Methoden */
    };
    


  • seldon schrieb:

    Die Antwort auf deine Wünsche dürfte Boost.Format sein.

    Boost.Format ist auf jeden Fall interessant, leider werde ich wohl etwas doof angeguckt, wenn ich plötzlich im gesamten Projekt alle RString Konstruktoraufrufe verändere. In dem Sinne werde ich das mal für zukünftige Projekte im Hinterkopf behalten (und mir Boost allgemein noch mal weiter anschauen... da gibt es ja fast alles).

    @Sone:
    Woher der erste Konstruktor kommt, weiß ich leider selbst nicht genau. Ich vermute mal, dass er genutzt werden sollte, um unnötige Aufrufe an vsprintf zu vermeiden, wenn diese nicht benötigt werden.

    @arrrrrrrrrrrrrr:
    Dein Ansatz passt in diesem Fall am besten, auch wenn ich ihn umgekehrt implementiert habe (Standardmäßig vararg, RString::noformat für mein im Startpost genannten Anwendungsfall).

    In diesem Sinne also vielen Dank an euch 👍 😉

    PS:
    Anscheinend ist hier eine Veränderung am Visual C++ Compiler vorgenommen werden, der obrige Quellcode lief unter VC++ 2008 problemlos, wie mir nach Rücksprache von einem Bekannten mitgeteilt wurde.


Anmelden zum Antworten