2015-10-18 14 views
10

Modifica: ho riformattato il post per essere più chiaro.Perché l'aggiunta di due letterali stringa non utilizza l'operatore + (const string &, const string &)?

Perché questo lavoro:

struct A {}; 

struct B { 
    B(A){} 
}; 

void operator+(const B&, const B&) {} 

int main() 
{ 
    A a1, a2; 
    a1 + a2; 
} 

e questo non lo fa?

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"; 
} 

In sostanza, nel primo esempio a1 e a2 sia convertire in B oggetti attraverso la conversione implicita e utilizzare il operator+(const B&, const B&) da aggiungere.

Seguendo da questo esempio, mi sarei aspettato "Hello" e "world" convertire in B oggetti, sempre attraverso il costruttore implicita, e utilizzare operator+(const B&, const B&) per aggiungere gli uni agli altri. Invece c'è un errore, che indica che le stringhe in stile C non tentano una conversione definita dall'utente in B per aggiungere. Perchè è questo? Esiste una proprietà fondamentale che impedisce questo?

+1

Non si è trattato di 'std :: string' con' "stack" + "overflow"; '. –

+1

@ πάνταῥεῖ È a conoscenza di ciò, la domanda è perché la conversione implicita in 'std :: string' non risolve il problema per lui. –

+1

Il tuo esempio minimale è un po 'off poiché 'const char *' non ha alcun operatore di conversione, ma la conversione avviene tramite il costruttore 'std :: string's. [Questo] (http://coliru.stacked-crooked.com/a/1c4aafeb95886b92) sarebbe un po 'più adatto. –

risposta

5

Nel vostro primo esempio, la risoluzione di sovraccarico è ha permesso di trovare il tuo 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 .[..]

(Si può esaminare il testo "sequenza di conversione implicita" voi stessi per vedere che l'ho chiamata operator+ s ammissibile; le regole sono troppo prolisso per giustificare riproduzione letterale qui.)

Tuttavia, nel secondo esempio, la risoluzione di sovraccarico è vincolato a un meccanismo di addizione aritmetica di base (uno che non è definito per const char[N] o const char*), in modo efficace che vieta qualsiasi operator+ funzione da considerare:

[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

Buona risposta.Grazie a te e @BaummitAugen soprattutto per l'aiuto con questo (e anche con tutti gli altri). – Silversonic

+0

@ Silversonic: è stato divertente! #Cosa c'è di sbagliato in me –

2

1. Spiegando il vostro errore di compilazione:

Il motivo non è possibile concatenare due stringhe letterali utilizzando l'operatore '+',
è perché le stringhe letterali sono semplicemente array di caratteri, e si puo' t concatenare due array.

Le matrici verranno convertite implicitamente nel puntatore del loro primo elemento.

O come standard lo descrive:

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

Quello che state realmente facendo nell'esempio di cui sopra,
sta cercando di aggiungere due puntatori const char insieme, e che non è possibile.


2. Perché le stringhe letterali non sono implicitamente convertiti:

Dal vettori e puntatori sono tipi fondamentali, non è possibile fornire un operatore conversazione implicita come avete fatto nel tuo esempio di classe .

La cosa principale da tenere a mente, è che std::string sa come prendere in char[], ma char[] non sa come diventare un std::string. Nel tuo esempio, hai utilizzato B, in sostituzione di char[], ma hai anche dato la possibilità di convertirsi a A.


3. Alternative:

è possibile concatenare stringhe, lasciando fuori l'operatore più.

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

Opzionalmente, si potrebbe fare "stack" di uno std :: string, e poi usare '+' operatore std :: della stringa di sovraccarico:

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

Questo non spiega perché la conversione implicita a 'std :: string' non si verifica. –

+2

Come menziona @BaummitAugen, questa risposta non spiega perché entrambi gli operandi 'char *' non possono essere convertiti in 'string' da conversioni definite dall'utente e' operator + (const string &, const string &) 'essere usato. – Silversonic

+0

Puoi citare la sezione pertinente dello standard C++? Perché c'è una risposta che lo fa ed è completamente diverso (basato sul fatto che la stringa sia un modello). –

Problemi correlati