2014-10-02 9 views
6

La domanda Lambda expressions as class template parameters richiede la possibilità di utilizzare espressioni lambda come parametri del modello di classe.Espressioni lambda come parametri del modello di classe in C++ 14

La risposta alla domanda era no. Tuttavia, si trattava di C++ 11.

La situazione è cambiata nel nuovo standard, C++ 14?

+4

Le regole sono state rafforzate in C++ 14 e considerando [le ragioni per escluderle formano operandi non valutati] (http://stackoverflow.com/a/22232165/1708801) Non penso che cambierà. –

+0

Data l'ultima bozza, il testo citato (con enfasi) nel post collegato non è cambiato. Quindi penserei, no, la situazione non era cambiata. – Niall

+1

Er ... La risposta era sì, ma non direttamente. Rendere la mia risposta, che era anche "sì, solo non direttamente" per C++ 14, in qualche modo inutile. – hvd

risposta

2

No la situazione in C++ 14 non è cambiato affatto e infatti la lingua nella sezione 5.1.2Espressioni lambda paragrafo 2 è stato serrato da:

Un lambda-espressione non deve appaiono in un operando non valutato (clausola 5).

a:

[...] A lambda-espressione non deve apparire in un operando non valutata (clausola 5), ​​in un templateargument, in un alias-dichiarazione, in un typedef dichiarazione, o nella dichiarazione di una funzione o funzione modello al di fuori del suo corpo funzione e argomenti predefiniti. [Nota: l'intenzione di è di impedire che lambda appaia in una firma. -end nota] [...]

Defect report 1607. Lambdas in template parameters portare a questa modifica.

Il rapporto sui difetti riguarda solo in modo obliquo le motivazioni alla base di ciò, ma possiamo trovare una spiegazione molto dettagliata del motivo per cui questo non è consentito in Rationale for lambda-expressions not being allowed in unevaluated contexts. I motivi si riducono a:

  • Espressioni lambda non avere un unico tipo
  • Compiler problemi di implementazione:
    • Come una straordinaria espansione del SFINAE
    • L'eventuale obbligo di nome Mangle tutto corpo di un lambda.

Dato il razionale per questa restrizione sembra improbabile che cambi.

1

La situazione è cambiata nel nuovo standard, C++ 14?

Un lambda espressione non deve ancora apparire in un operando non valutata - la stessa citazione di quello in Xeo's Post esiste anche nel più recente progetto a disposizione del pubblico N3797, nella stessa identica posizione.

Tuttavia, ogni tipo di chiusura presenta un costruttore di default soppresso (N3797, §5.1.2/20):

Il tipo di chiusura associato con un lambda-espressione ha un eliminato (8.4.3) costruttore predefinito e un operatore di assegnazione copie cancellato.

Così, per portabiliby e la conformità standard (e, probabilmente, per il codice di lavorare su compilatori ragionevoli), si avrebbe bisogno di passare un oggetto chiusura al costruttore della classe istanziata da cui copiare. Ma per passare un oggetto chiusura dello stesso tipo come argomento di modello che la specializzazione è necessario definire per prima in ogni caso:

using my_map_type = map<int, int, decltype([] (auto&& lhs, auto&& rhs) {return lhs < rhs*4;})>; 
// Assuming the above compiles 

my_map_type m([] (auto&& lhs, auto&& rhs) {return lhs < rhs*4;}); 
// Different closure type - compiler error! What do you copy from!? 

Non c'è alcun modo legale per creare un singolo oggetto del tipo di chiusura del primo lambda. Pertanto, anche se tale regola dovesse essere rimossa, non è possibile creare una singola istanza di my_map_type. Problemi simili si verificano con altri scenari "tipo di chiusura come argomento modello".

+0

* "Un'espressione Lambda non deve ancora apparire in un operando non valutato" * Ma può apparire in una parte non valutata di un'espressione costante. Questo permette anche di usare lambda senza cattura se non si dispone di un oggetto di chiusura, vedi http://pfultz2.github.io/Pythy/ – dyp

+0

@ dyp Non è di questo che si tratta. – Columbo

+0

Sì, ma è ciò di cui la tua risposta sembra essere (ai miei occhi). È possibile passare il tipo di lambda a un modello e creare un puntatore nullo del tipo lambda. Se il lambda non ha cattura, puoi chiamarlo attraverso quel puntatore nullo. Cioè, * puoi * in realtà passare alcuni lambda tramite il loro tipo a un modello. – dyp

Problemi correlati