2015-03-03 6 views
8

Wenn SFINAE für einen beliebigen Typ ausgeführt wird, muss das Ergebnis eines Ausdrucks oft in void umgewandelt werden. Ich habe zwei Möglichkeiten gesehen, dies zu tun; ein gegossenes ungültig zu erklären:SFINAE: 'static_cast <void>()' oder ', void()'?

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

Oder alternativ den Komma-Operator mit einem Hohlraum prvalue RHS mit:

(expr), void() 

Es ist mein Verständnis, dass in beiden Fällen expr (für Wohlgeformtheits- ausgewertet wird, in ein nicht evaluierter Kontext) und das Ergebnis (oder der Ergebnistyp in einem nicht evaluierten Kontext) verworfen wird; es ist in keinem Fall möglich, selbst eine pathologische Klasse T zu überschreiben T::operator void() oder operator,(T, void). (Siehe: Why is "operator void" not invoked with cast syntax?, What does the 'void()' in 'auto f(params) -> decltype(..., void())' do?).

Das heißt, sind diese beiden Idiome gleichwertig, oder gibt es irgendwelche Umstände, unter denen man dem anderen vorzuziehen ist (möglicherweise mit Nichtstandard-Compilern)? Wenn nicht, gibt es irgendwelche Gründe (z. B. Verständlichkeit), einander vorzuziehen?

+0

Ich würde nur die kürzeste und klarste Notation verwenden. Wenn es eine Subtilität geben sollte, die die Verwendung des Komma-Ausdrucks erzwingen würde, würde ich das für diesen speziellen Fall verwenden, mit einem Kommentar, der erklärt, warum. Ich kann mir keine solche Subtilität vorstellen. –

Antwort

2

Beide erfüllen die Anforderungen benötigt:

  • Verlangen, dass expr als verworfenen Wertausdruck gültig und nur dass.
  • haben immer Typ void (zur Verwendung in Rückgabetypen nachlauf oder partial specializations)

Somit können die Verfahren gleichwertig sind, wenn die obigen Kriterien berücksichtigen. In diesem Sinne, würde ich empfehlen, zu verwenden, was in Ihrem Code prägnanter ist; aber was auch immer Sie wählen, halten Sie sich an die Konsistenz.
Man kann auch einen funktionalen Casts verwenden, da es per Definition entspricht die explizite Umwandlung Notation ist, wenn es nur ein Argument ist - das heißt

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

funktioniert auch.

1

Der Unterschied ist im Grunde stilistisch.

In einigen Fällen kann das Formular void() aufgrund der niedrigen Priorität des Komma-Operators ein zusätzliches Klammerpaar vermeiden. Zum Beispiel, foo + bar, void() funktioniert gut, aber (void) (foo + bar) (oder die funktionale Art Cast Äquivalent) erfordert Klammerung der gesamte Ausdruck.

In anderen Fällen kann die Verwendung eines (void) Cast prägnanter sein. Um beispielsweise vor überlasteten Kommas in ++it1, ++it2, ++it3 zu schützen, können Sie einen (void) Cast - ++it1, (void) ++it2, ++it3 verwenden, aber um void() zu verwenden, müssten Sie zweimal schreiben: ++it1, void(), ++it2, void(), ++it3.

0

Wird auf ungültig gesetzt, da das Komma überlastet werden kann.

+0

Es gibt einen ganzen Absatz, der zeigt, dass OP weiß, * warum * diese Muster existieren. Er bittet um einen Vergleich zwischen ihnen. – Quentin

+0

Der Komma-Operator kann nicht überladen werden, wenn einer der Operanden "void" ist. – ecatmur