"bar"
is of type char const [4]
, and the conversion from that to a bool
is an standard conversion sequence, while conversion to std::string
is a user defined conversion. The former is always preferred over the latter.
From N3337, [conv]/1
Standard conversions are implicit conversions with built-in meaning. Clause 4 enumerates the full set of such conversions. A standard conversion sequence is a sequence of standard conversions in the following order:
— Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion,
and function-to-pointer conversion.
— Zero or one conversion from the following set: integral promotions, floating point promotion, integral
conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to member conversions, and boolean conversions.
— Zero or one qualification conversion.
In your example, the standard conversion sequence consists of array-to-pointer conversion and boolean conversion.
[conv.array]/1
An lvalue or rvalue of type “array of N T
” or “array of unknown bound of T
” can be converted to a prvalue of type “pointer to T
”. The result is a pointer to the first element of the array.
[conv.bool]/1
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool
. A zero value, null pointer value, or null member pointer value is converted to false
;
any other value is converted to true
. ...
Thus Test("foo", "bar")
results in a call to the Test(const string&, bool)
constructor instead of the other one.
One way to trigger a call to the other constructor would be to use string_literals
using namespace std::literals::string_literals;
Test("foo", "bar"s); // calls Test(const string&, const string&, bool)
// ^