Why does the compiler choose bool over string for implicit typecast of L“”?

后端 未结 5 2050
没有蜡笔的小新
没有蜡笔的小新 2020-12-01 19:12

Having recently introduced an overload of a method the application started to fail. Finally tracking it down, the new method is being called where I did not expect it to be.

相关标签:
5条回答
  • 2020-12-01 19:35

    To simplify a bit, the following code

    #include <iostream>
    using namespace std;
    
    void f(const string &s)
    {  cout << "string version called" << endl;  }
    
    void f(const bool &b)
    {  cout << "bool version called" << endl;  }
    
    int main()
    {  f("Hello World");  }
    

    prints "bool version called". Are you sure that your code fails only with the empty string?

    0 讨论(0)
  • 2020-12-01 19:37

    First, the cause of this issue: C++ Standard [over.ics.rank]/2.11 defines an order for conversion sequences. It says that a user defined conversion sequence is worse than a standard conversion sequence. What happens in your case is that the string literal undergoes a boolean-conversion (defined at 4.12. This is a standard conversion). It does not use the user defined conversion to std::wstring which would be needed if it took the other overload.

    I would recommend to simply change the name of one of the overloads or adding an overload that accepts the string literal directly (using parameter type wchar_t const*).


    1)

    When comparing the basic forms of implicit conversion sequences (as defined in [over.best.ics])

    (2.1) a standard conversion sequence is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and
    (2.2) a user-defined conversion sequence is a better conversion sequence than an ellipsis conversion sequence.

    0 讨论(0)
  • 2020-12-01 19:39

    Since bool is a built-in type, the conversion from wchar_t to bool is preferred. I would say that the simplest solution is to add an overload that takes a wchar_t array and cast explicitly in there:

    setValue( const std::wstring& name, const wchar_t s[] )
    {
         setValue(name, wstring(s));
    }
    
    0 讨论(0)
  • 2020-12-01 19:40

    You could make the new function take some other type than bool--maybe just a proxy for bool--which is not convertible from a literal string. But really I'd just rename the bool-taking function and be done with it.

    0 讨论(0)
  • 2020-12-01 19:46

    L"" is a pointer to a wide character string. The compiler believes that the conversion to a bool takes precedence over a conversion to a std::wstring.

    To fix the problem, introduce a new setValue:

    void setValue(std::wstring const& name, const wchar_t * value);
    
    0 讨论(0)
提交回复
热议问题