Edit: I have reformatted the post to be clearer.
Why does this work:
struct A {};
struct B {
B(A){}
};
void operator+(const B&, const B&) {}
int main()
{
A a1, a2;
a1 + a2;
}
and this does not?
struct B {
B(const char*){}
};
void operator+(const B&, const B&) {} //error: invalid operands of types 'const char [6]' and 'const char [6]' to binary 'operator+'|
int main()
{
"Hello" + "world";
}
Essentially, in the first example a1
and a2
both convert to B
objects through the implicit conversion and use the operator+(const B&, const B&)
to add.
Following from this example, I would have expected "Hello"
and "world"
to convert to B
objects, again through the implicit constructor, and use operator+(const B&, const B&)
to add to each other. Instead there is an error, which indicates the C-style strings do not attempt a user-defined conversion to B
in order to add. Why is this? Is there a fundamental property that prevents this?
In your first example, overload resolution is allowed to find your operator+
:
[C++14: 13.3.1.2/2]:
If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator. In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator. [..]
[C++14: 13.3.2/1]:
From the set of candidate functions constructed for a given context (13.3.1), a set of viable functions is chosen, from which the best function will be selected by comparing argument conversion sequences for the best fit (13.3.3). The selection of viable functions considers relationships between arguments and function parameters other than the ranking of conversion sequences.
[C++14: 13.3.2/2]:
First, to be a viable function, a candidate function shall have enough parameters to agree in number with the arguments in the list.
- If there are
m
arguments in the list, all candidate functions having exactlym
parameters are viable.- [..]
[C++14: 13.3.2/3]
: Second, forF
to be a viable function, there shall exist for each argument an implicit conversion sequence (13.3.3.1) that converts that argument to the corresponding parameter ofF
. [..]
(You may examine the wording for "implicit conversion sequence" yourself to see that the operator+
call is permissible; the rules are too verbose to warrant verbatim reproduction here.)
However, in your second example, overload resolution is constrained to a basic arithmetic addition mechanism (one which is not defined for const char[N]
or const char*
), effectively prohibiting any operator+
function from being considered:
[C++14: 13.3.1.2/1]:
If no operand of an operator in an expression has a type that is a class or an enumeration, the operator is assumed to be a built-in operator and interpreted according to Clause 5.
[C++14: 5.7/1]:
[..] For addition, either both operands shall have arithmetic or unscoped enumeration type, or one operand shall be a pointer to a completely-defined object type and the other shall have integral or unscoped enumeration type. [..]
[C++14: 5.7/3]:
The result of the binary + operator is the sum of the operands.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With