2015-03-03 12 views
8

Podczas wykonywania SFINAE na dowolnym typie, często konieczne jest rzutowanie wyniku wyrażenia na void. Widziałem dwa sposoby robienia tego; oddanych do unieważnienia:SFINAE: 'static_cast <void>()' lub ', void()'?

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

albo, alternatywnie, za pomocą operatora przecinek w pustce prvalue RHS:

(expr), void() 

To moja zrozumienie, że w obu przypadkach expr jest oceniany (dla sensowności, w kontekst nieoceniony) i odrzucono wynik (lub typ wyniku, w kontekście nieocenionym); w obu przypadkach nie jest możliwe, aby nawet klasa patologiczna T nadpisała T::operator void() lub operator,(T, void). (Zobacz: Why is "operator void" not invoked with cast syntax?, What does the 'void()' in 'auto f(params) -> decltype(..., void())' do?).

To powiedziawszy, czy te dwa idiomy są równoważne, czy są jakieś okoliczności, w których jeden powinien być preferowany względem drugiego (być może z niestandardowymi kompilatorami)? Jeśli nie, to czy istnieją jakieś powody (np. Zrozumiałość), aby preferować jeden z drugim?

+0

Po prostu użyłbym najkrótszej i najbardziej przejrzystej notacji. Gdyby istniała jakaś subtelność, która wymuszałaby użycie wyrażenia przecinka, użyłbym tego w tym konkretnym przypadku, z komentarzem wyjaśniającym dlaczego. Nie mogę sobie jednak wyobrazić takiej subtelności. –

Odpowiedz

2

Oboje spełniają wymagania niezbędne:

  • Wymagaj że expr ważne jako wyrażenie odrzucane-wartości, a tylko że.
  • Zawsze typu void (do zastosowania w spływu typu powrotne lub partial specializations)

Zatem metody te są równoważne, rozważając powyższe kryteria. Pamiętając o tym, polecam użyć tego, co jest bardziej zwięzłe w kodzie; ale cokolwiek wybierzesz, trzymaj się go dla spójności.
Można również użyć funkcjonalnym stylu obsady, ponieważ z definicji jest równoważna notacji szarego wyraźnej gdy istnieje tylko jeden argument - to znaczy

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

również działa.

1

Różnica jest w zasadzie stylistyczna.

W niektórych przypadkach, z powodu niskiego pierwszeństwa operatora przecinka, formularz void() może uniknąć dodatkowej pary nawiasów. Na przykład: foo + bar, void() działa dobrze, ale (void) (foo + bar) (lub równoważny odlew w stylu funkcjonalnym) będzie wymagał nawiasowania całego wyrażenia.

W innych przypadkach użycie obsady (void) może być bardziej zwięzłe. Na przykład, aby zabezpieczyć się przed przeciążeniem przecinków w ++it1, ++it2, ++it3, można użyć jednego odlewu (void) - ++it1, (void) ++it2, ++it3, ale użycie void() wymagałoby zapisania go dwukrotnie: ++it1, void(), ++it2, void(), ++it3.

0

Oddane do skutku, ponieważ przecinek może być przeciążony.

+0

Istnieje cały akapit, który pokazuje, że OP wie, * dlaczego * te wzorce istnieją. Poprosił o porównanie między nimi. – Quentin

+0

Operator przecinka nie może być przeciążony, gdy jeden z argumentów jest "void". – ecatmur

Powiązane problemy