Why does adding two string literals not use operator+(const string&, const string&)?

对着背影说爱祢 提交于 2020-08-22 04:44:08

问题


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?


回答1:


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 exactly m parameters are viable.
  • [..]

[C++14: 13.3.2/3]: Second, for F 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 of F. [..]

(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.




回答2:


1. Explaining your compiler error:

The reason you can't concatenate two string literals using the '+' operator,
is because string literals are simply arrays of characters, and you can't concatenate two arrays.

Arrays will be implicitly converted to the pointer of their first element.

Or as the standard describes it:

[conv.array]
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.

What you are really doing in the example above,
is trying to add two const char pointers together, and that is not possible.


2. Why the string literals aren't implicitly converted:

Since arrays and pointers are fundamental types, you can't provide an implicit conversation operator as you have done in your class example.

The main thing to keep in mind, is that std::string knows how to take in char[], but char[] does not know how to become a std::string. In your example, you've used B, as a replacement to char[], but you've also given it the ability to convert itself to A.


3. Alternatives:

You can concatenate string literals by leaving out the plus operator.

"stack" "overflow"; //this will work as you indented

Optionally, you could make "stack" a std::string, and then use the std::string's overloaded '+' operator:

std::string("stack") + "overflow"; //this will work


来源:https://stackoverflow.com/questions/33202400/why-does-adding-two-string-literals-not-use-operatorconst-string-const-strin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!