2015-03-10 12 views
11

quanto ne know, nello standard C++ 11 (non C++ 14), quando omettendo il tipo di ritorno di un lambda, il tipo restituito è dedotta per essere:Quando possiamo omettere il tipo restituito in un lambda C++ 11?

  1. Il tipo di l'espressione restituita, ogni volta che il lambda consiste in nient'altro che una singola istruzione di ritorno con un'espressione, oppure
  2. void in tutti gli altri casi.

consideri ora questo codice:

#include <iostream> 

auto closure = [](int x) 
{ 
    x++; 
    return x; 
}; 

int main() 
{ 
    int y = closure(10); 
    std::cout << y << std::endl; 
} 

Questo dovrebbe rientrare in caso 2., tuttavia il codice viene compilato come se fosse C++ 14 con auto tipo deduzione, sia g ++ 4.9.2 , g ++ 5 e clang ++, con -pedantic -Wall -Wextra -std=c++11. Cosa sta succedendo qui? Sto interpretando lo standard sbagliato?

+0

vedere [è la discussione del mio libro di tipi restituiti Lamba sbagliato?] (Http://stackoverflow.com/q/14738335) Inoltre, [Quando possiamo omettere il tipo di ritorno in C++ 11 lambda?] (Http : //stackoverflow.com/q/28955478), [? Perché le funzioni lambda drop dedurre il tipo di ritorno di riferimento di default] (http://stackoverflow.com/q/41534031) e [esplicita ritorno tipo di Lambda] (http: //stackoverflow.com/q/9620098). – jww

risposta

10

Il codice viene accettato senza alcun avviso poiché la limitazione C++ 11 originale è considerata un difetto nello standard, che consente alle implementazioni di correggere il comportamento. Vedere CWG DR975, DR1048 e N3638.

975. Restrizioni al tipo di ritorno deduzione per lambda

[Spostato allo status di DR al mese di aprile, 2013 incontro come parte della carta N3638.]

Ci non sembra essere alcun difficoltà tecnica che richiederebbe l'attuale restrizione che il tipo di ritorno di una lambda può essere dedotta solo se il corpo della lambda consiste in una dichiarazione di reso unica. In particolare, potrebbero essere consentite più dichiarazioni di reso se tutte restituiscono lo stesso tipo.

1048. deduzione tipo di detrazione automatica e detrazione.

...

Note dal novembre 2014 incontro:

CWG convenuto che il cambiamento incarnata in carta N3638 dovrebbe essere considerato di essere stato un DR contro C++ 11 .

In sintesi, DR975 ha proposto di modificare le regole per la deduzione del tipo restituito per espressioni lambda per consentire più dichiarazioni di reso.

DR1048 identifica una discrepanza in cui le regole per dedurre il tipo di reso per le normali funzioni utilizzando il tipo di segnaposto auto differiscono leggermente dalle regole proposte in DR975. In particolare, la deduzione del tipo di ritorno per le normali funzioni eliminerebbe i qualificatori di cv di primo livello in tutti i casi, mentre quelli per le espressioni lambda preserverebbero i qualificatori di cv per i tipi di classe.

N3638 risolve questo problema, tra gli altri.


Dubito che ci sia un modo per ripristinare il comportamento originali a corto di trovare una versione del compilatore fornito con C++ 11 sostegno lambda prima dell'attuazione del DR sopra.

+0

Sono ancora un po 'confuso. Il corpo di lambda può consistere in più affermazioni, ma solo una dichiarazione di ritorno, o il suo intero corpo deve consistere in una sola dichiarazione di ritorno per applicare il mio caso 1.? – vsoftco

+0

In realtà, la proposta di risoluzione non è stata adottata. Invece, [N3638] (https://isocpp.org/files/papers/N3638.html) è stato, e quindi [DR1048] (http://www.open-std.org/jtc1/sc22/wg21/docs/ cwg_defects.html # 1048) ha chiarito che i cambiamenti N3638 per lambda deve essere considerato un DR contro C++ 11. –

+0

@ T.C. Proprio sotto il DR ho collegato a: S, dovevo continuare a leggere. Grazie. – Praetorian

3

Alcune regole C++ 14 sono disponibili in modalità C++ 11, quando gli scrittori del compilatore consideravano troppo complicato implementare entrambe le regole contemporaneamente.

+0

Quindi, in teoria, il mio codice non è al 100% compatibile con C++ 11, giusto? – vsoftco

+0

Sì, sembra che non sarebbe accettato in C++ 11. –

+0

Penso che si possa usare l'operatore virgola per renderlo una singola istruzione, quindi sarà compatibile con C++ 11 –

2

Questo è quello che trovo in C++ Draft standard N3337:

Se un lambda-espressione non include un lambda-dichiaratore, è come se il lambda-dichiaratore erano(). Se un lambda-espressione non include una trailing-ritorno-tipo, è come se il trailing-ritorno-tipo denota il seguente tipo:

- se il composto-statement è di forma

{attributo-specificatore-seqoptreturnespressione; }

il tipo dell'espressione restituita dopo la conversione da lvalue a rvalue (4.1), la conversione da matrice a puntatore (4.2) e la conversione da funzione a puntatore (4.3);

- altrimenti, void.

[Esempio:

auto x1 = [](int i){ return i; }; // OK: return type is int 
auto x2 = []{ return { 1, 2 }; }; // error: the return type is void (a 
            // braced-init-list is not an expression) 

- esempio end]

La norma sembra indicare che:

  • Quando una sola istruzione è presente, e
  • Si tratta di una dichiarazione di ritorno, e
  • L'oggetto che viene restituito è un'espressione

Poi il tipo di ritorno si deduce dalla espressione. In caso contrario, il tipo di reso è void.

+0

sì, così sembra che il corpo del lambda dovrebbe consistere solo di 'restituire qualcosa;' – vsoftco