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.
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?
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.
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));
}
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.
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);