2016-02-11 26 views
7

Voglio scrivere una lambda che prende un numero arbitrario di argomenti per riferimento universale e li ignora completamente. Il metodo ovvia sarebbe quella di utilizzare la sintassi per un parametro di variadic pacchetto universale e omettere il nome del parametro:Come scrivere un lambda variadico generico che scarta i suoi parametri?

auto my_lambda = [](auto&&...) { return 42; }; 

Questo funziona bene (con gcc 4.9.2) fino a quando ho try to pass a non trivially-copyable object:

struct S { S() {} S(S const&) {} }; 
my_lambda("meow", 42, S{}); 
^ error: cannot pass objects of non-trivially-copyable type 'struct S' through '...' 

Cosa c'è sta succedendo? Il mio codice è malformato o si tratta di un bug in gcc?

In entrambi i casi, qual è la soluzione migliore? Ho scoperto che nominare il parametro funziona, ma poi mi sono imbattuto in un inutilizzato-parametro di avvertimento:

auto my_lambda = [](auto&&... unused) { return 42; }; 
^ error: unused parameter 'unused#0' [-Werror=unused-parameter] 
^ error: unused parameter 'unused#1' [-Werror=unused-parameter] 
^ error: unused parameter 'unused#2' [-Werror=unused-parameter] 

Come si fa a sopprimere un avviso inutilizzato parametro su un pacchetto parametro di modello?

+3

Sembra un bug GCC. Funziona] (http://coliru.stacked-crooked.com/a/e1b37f5289b7c8ec) in 5.2. – TartanLlama

+0

@TartanLlama Per alcune definizioni di "opere". 5.2 supporta il passaggio di oggetti non banali-copiabili tramite '...', ma il bug di parsing non è corretto, IIRC. –

risposta

10

È un parsing bug in GCC (che tu stesso hai segnalato!). auto&&... è grammaticalmente ambiguo e possono essere analizzati sia come l'equivalente di auto&&, ... o una dichiarazione di parametro pacco (tecnicamente, ci si chiede se ... fa parte del parametro dichiarazione clausola o astratta-declarator); lo standard dice che deve essere analizzato come quest'ultimo; GCC lo analizza come il primo.

Dare un nome al pacchetto risolve l'ambiguità di analisi:

auto my_lambda = [](auto&&... unused) { return 42; }; 

Per eliminare l'avviso, si potrebbe applicare __attribute__((__unused__)) (o, come suggerito @Luc Danton, [[gnu::unused]]):

auto my_lambda = [](auto&&... unused __attribute__((__unused__))) { return 42; }; 

o utilizzare sizeof...

auto my_lambda = [](auto&&... unused) { (void) sizeof...(unused); return 42; }; 
+1

Dato che GCC è menzionato, 'type var [[gnu :: inutilizzato]]' è un'alternativa a 'type var __attribute __ ((__ inutilizzato __))' (Dimentico comunque quale versione). –

+2

@LucDanton e, infine, '[[forse_unused]]'. –