VC++ Compiler ruft falschen Konstruktor auf



  • Ich bin gerade auf ein eigenartiges Verhalten meines VC++ Compilers (VS2008 SP1) gestoßen. Unicode ist aktiv, Debug Modus an (--> keine Optimierungen).

    Ich habe folgende Klasse:

    typedef std::wstring tstring;
    class CIniFileWriter : virtual public CIniFileBase
    {
      public:
        explicit CIniFileWriter(bool bFlushAfterWrite = false, bool bFlushOnClose = true) throw(); // Version 1
        explicit CIniFileWriter(const tstring& Filename, const tstring& SectionName, bool bFlushAfterWrite = false, bool bFlushOnClose = true) throw(); // Version 2
        explicit CIniFileWriter(const tstring& Filename, bool bFlushAfterWrite = false, bool bFlushOnClose = true) throw(); // Version 3
    
      private:
        CIniFileWriter(const CIniFileWriter& rhs);
    };
    

    In CIniFileBase gibt es keine öffentlichen Konstruktoren.

    Der Compiler beharrt jetzt darauf, strings in bools anstatt in std::string/std::wstring zu konvertieren...

    CIniFileWriter IniWriter(_T("Test2.ini"), _T(""), false); // --> Version 3 anstatt Version 2
    CIniFileWriter IniWriter(_T("Test2.ini")); // Version 1 statt 3
    CIniFileWriter IniWriter(_T("Test2.ini"), _T("")); // Version 1 statt 2
    CIniFileWriter IniWriter(tstring(_T("Test2.ini")), _T("")); // Version 3 anstatt 2
    CIniFileWriter IniWriter(tstring(_T("Test2.ini"))); // Version 3 (korrekt)
    CIniFileWriter IniWriter(_T("Test2.ini"), true); // Version 1 statt 3
    

    IntelliSense zeigt mir nur Version 2, 3 und den Copyconstructor an...

    Ich hab keine Ahnung was der Compiler macht... 😮



  • Nö das passt schon. Ist bloss nicht was du erwartet hast. Und zugegebenermassen wahrscheinlich etwas was viele nicht erwartet hätten. Aber trotzdem genau das was der Standard vorschreibt.

    Lässt sich auf folgendes reduzieren:

    #include "stdafx.h"
    
    #include <string>
    #include <iostream>
    
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    void foo(std::string const& s)
    {
    	std::cout << "std::string const&\n";
    }
    
    void foo(bool b)
    {
    	std::cout << "bool\n";
    }
    
    int main(int argc, char** argv)
    {
    	std::cout << "bool -> ";
    	bool b = false;
    	foo(b); // bool - klar
    
    	std::cout << "std::string -> ";
    	std::string s;
    	foo(s); // std::string const& - auch klar
    
    	std::cout << "const char* -> ";
    	const char* ccp = "";
    	foo(ccp); // bool - die "user defined conversion" const char* -> std::string ist "schlechter" als die eingebaute konvertierung nach bool
    
    	std::cout << "string literal -> ";
    	foo(""); // bool - selbe wie oben: eingebaute konvertierung "besser" als selbst definierte
    }
    

    In dem von dir geschilderten Fall ist das zwar doof, aber grundsätzlich: woher soll der compiler wissen wann eine user-defined-conversion besser ist, als eine eingebaute? Die Entscheidung "user-defined ist immer schlechter" ist halt einfach und "sicher".

    Lösung: const wchar_t* overloads machen.



  • Mh, so gesehen ist das wirklich logisch^^ (keine Ironie!)

    Danke für die Erklärung und den Lösungsvorschlag 👍


Log in to reply