2014-11-01 3 views
10

sto leggendo qui su cppreference su come un tipo di ritorno di un lambda C++ 11 si deduce:C++ 11 restrizioni sul tipo di ritorno lambda

if the body consists of the single return statement, the return type is the type of the returned expression (after rvalue-to-lvalue, array-to-pointer, or function-to-pointer implicit conversion)

Quindi penso che significa che una lambda può ha solo una dichiarazione di ritorno. Ma perché funziona ancora con più dichiarazioni di ritorno?

Questo compiles su entrambi i compilatori:

auto f = [] (bool c1, bool c2) { 
    if (c1) return 1; 
    if (c2) return 2; 
    else return 3; 
}; 
+2

La pagina che collega a mostra anche che le regole sono cambiate in C++ 14. La mia prima ipotesi è che i compilatori stiano implementando le regole del C++ 14 anche in modalità C++ 11. – hvd

+0

@hvd Sì, questo è quello che sospettavo ma ero ancora scettico. – 0x499602D2

+0

FWIW, ho controllato cosa dice C++ 11 e corrisponde a quello che hai già trovato online, quindi sì, dovrebbe generare una diagnostica in fase di compilazione. Detto questo, l'implementazione della regola C++ 14 non può causare il rifiuto di un codice C++ 11 valido, quindi potrebbe essere solo un problema minore. – hvd

risposta

13

che è leggermente impreciso. [Expr.prim.lambda]/4:

If a lambda-expression does not include a lambda-declarator, it is as if the lambda-declarator were () . If a lambda-expression does not include a trailing-return-type, it is as if the trailing-return-type denotes the following type:

  • if the compound-statement is of the form

    {attribute-specifier-seqoptreturnexpression; }

    the type of the returned expression after lvalue-to-rvalue conversion (4.1), array-to-pointer conversion (4.2), and function-to-pointer conversion (4.3);

  • otherwise, void .

Così il tipo di ritorno si deduce solo se l'intero corpo dell'espressione lambda consiste solo in una sola return dichiarazione.

Sia GCC che Clang non sono conformi allo standard in questo caso poiché emettono un messaggio di errore se e solo se due dichiarazioni return portano a deduzioni incoerenti. Questo perché hanno già implementato lo standard C++ 14 che detrae il tipo restituito anche con più dichiarazioni return e/o più altre istruzioni presenti. [Expr.prim.lambda]/4 specifica che

The lambda return type is auto , which is replaced by the trailing-return-type if provided and/or deduced from return statements as described in 7.1.6.4.

§7.1.6.4/9

If a function with a declared return type that contains a placeholder type has multiple return statements, the return type is deduced for each return statement. If the type deduced is not the same in each deduction, the program is ill-formed.

+2

FWIW, [Ho chiesto informazioni su questo] (http://stackoverflow.com/questions/8582610/compiler-warning-lambda-return-type-cannot-be-deduced) anni fa :) – jrok

3

Funziona con il vostro esempio perché tutti i return dichiarazioni valori dello stesso tipo di ritorno. Ma provare a cambiare la seconda return a un tipo diverso, ad esempio:

auto f = [] (bool c1, bool c2) { 
    if (c1) return 1; 
    if (c2) return ""; 
    else return 3; 
}; 

compilazione questo con clangore ++ produce il seguente errore:

main.cpp:3:13: error: return type 'const char *' must match previous return type 'int' when lambda expression has unspecified explicit 
     return type 
    if (c2) return ""; 
     ^
1 error generated. 
+0

Chiede perché sono consentite più dichiarazioni di reso nonostante ciò che dice la citazione (che potrebbe essercene solo una). Questo non ha nulla a che fare con il tipo di espressione di ritorno. – 0x499602D2

+0

@ 0x499602D2 La citazione (incompleta) non dice che non sono consentite più istruzioni di reso. La citazione completa sembra implicare ciò, ma è semplicemente imprecisa. –

+0

@KonradRudolph Questo è ciò che pensa l'OP. – 0x499602D2