2015-03-03 26 views
8

Quando si esegue SFINAE su un tipo arbitrario, è spesso necessario trasmettere il risultato di un'espressione a void. Ho visto due modi per farlo; un cast a vuoto:SFINAE: 'static_cast <void>()' o ', void()'?

(void)(expr) // or static_cast<void>(expr) 

O, in alternativa, utilizzando l'operatore virgola con un vuoto prvalue RHS:

(expr), void() 

E 'la mia comprensione che in entrambi i casi expr viene valutata (per ben formati, in un contesto non valutato) e il risultato (o il tipo di risultato, in un contesto non valutato) scartati; in entrambi i casi non è possibile nemmeno una classe patologica T ignorare T::operator void() o operator,(T, void). (Vedi: Why is "operator void" not invoked with cast syntax?, What does the 'void()' in 'auto f(params) -> decltype(..., void())' do?).

Detto questo, questi due idiomi equivalgono o ci sono circostanze in cui si dovrebbe preferire l'altro (eventualmente con compilatori non standard)? In caso negativo, ci sono dei motivi (ad esempio, la comprensibilità) per preferire uno rispetto all'altro?

+0

Vorrei solo usare la notazione più breve e più chiara. Se ci dovrebbe essere qualche sottigliezza che imporrebbe l'uso dell'espressione virgola, lo userei per quel caso specifico, con un commento che spiega perché. Non riesco a pensare a una tale sottigliezza però. –

risposta

2

Entrambi soddisfano i requisiti necessari:

  • richiedono che expr essere valida come espressione valore eliminata ed solo che.
  • hanno sempre tipo void (per uso in uscita tipi restituiti o per partial specializations)

Così i metodi sono equivalenti quando si considerano i criteri di cui sopra. Tenendo presente questo, consiglierei di usare qualsiasi cosa più concisa nel codice; ma qualunque cosa scegliate, attenetevi ad essa per coerenza.
Si può anche utilizzare un cast stile funzionale, dal momento che è, per definizione, equivalente alla notazione cast esplicito quando c'è solo un argomento - vale a dire

auto g(auto f) -> decltype(void(f(1, 2, 3))); 

funziona anche.

1

La differenza è sostanzialmente stilistica.

In alcuni casi, a causa della bassa precedenza dell'operatore virgola, il modulo void() può evitare una coppia aggiuntiva di parentesi. Ad esempio, foo + bar, void() funziona perfettamente, ma l'(void) (foo + bar) (o l'equivalente cast dello stile funzionale) richiederà la parentesi dell'intera espressione.

In altri casi, l'utilizzo di un cast (void) può essere più conciso. Ad esempio, per proteggere da virgolette sovraccariche in ++it1, ++it2, ++it3, è possibile utilizzare un cast (void) - ++it1, (void) ++it2, ++it3, ma per utilizzare void() è necessario scriverlo due volte: ++it1, void(), ++it2, void(), ++it3.

0

Lanciare a vuoto perché la virgola può essere sovraccaricata.

+0

C'è un intero paragrafo che mostra che l'OP sa * perché * questi modelli esistono. Sta chiedendo un confronto tra loro. – Quentin

+0

L'operatore virgola non può essere sovraccaricato dove uno degli operandi è 'void'. – ecatmur