2015-03-03 2 views
8

При выполнении SFINAE на произвольном типе часто бывает необходимо передать результат выражения в void. Я видел два способа сделать это; литая к мочеиспусканию:SFINAE: 'static_cast <void>()' or ', void()'?

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

Или, в качестве альтернативы, используя оператор запятая с пустотой prvalue РИТ:

(expr), void() 

Это мое понимание того, что в обоих случаях expr оценивается (для оформленности, в не оцениваемый контекст), а результат (или тип результата в неоцениваемом контексте) отбрасывается; это невозможно в любом случае даже для патологического класса T для переопределения T::operator void() или operator,(T, void). (См .: Why is "operator void" not invoked with cast syntax?, What does the 'void()' in 'auto f(params) -> decltype(..., void())' do?).

Сказано, что эти два идиома эквивалентны, или существуют ли какие-либо обстоятельства, при которых предпочтение следует отдавать другому (возможно, с нестандартными компиляторами)? Если нет, есть ли какие-либо причины (например, понятность), чтобы они предпочитали друг друга?

+0

Я бы использовал кратчайшие и самые четкие обозначения. Если должна быть какая-то тонкость, которая заставит использовать выражение для запятой, я бы использовал это для этого конкретного случая с комментарием, объясняющим, почему. Хотя я не могу придумать такую ​​тонкость. –

ответ

2

Они оба отвечают необходимым требованиям:

  • Требовать expr быть действительным как выражение отбрасываются-значение, и только что.
  • всегда имеет тип void (для использования в задних типах возвращаемых или для partial specializations)

Таким образом, методы эквивалентны при рассмотрении вышеуказанных критериев. Помня об этом, я бы рекомендовал использовать все, что более кратким в вашем коде; но что бы вы ни выбрали, придерживайтесь его для согласованности.
Можно также использовать функциональный актерский стиль, так как она по определению эквивалентна явной литой нотации, когда есть только один аргумент - то есть

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

также работает.

1

Разница в основном стилистическая.

В некоторых случаях из-за низкого приоритета оператора запятой форма void() может избежать дополнительной пары круглых скобок. Например, foo + bar, void() работает просто отлично, но (void) (foo + bar) (или эквивалент литья в функциональном стиле) потребует скобки для всего выражения.

В других случаях использование литья (void) может быть более кратким. Например, чтобы защитить от перегруженных запятых в ++it1, ++it2, ++it3, вы можете использовать один (void) литой - ++it1, (void) ++it2, ++it3, но для использования void() потребуется записать его дважды: ++it1, void(), ++it2, void(), ++it3.

0

Отклонено, поскольку запятая может быть перегружена.

+0

Существует целый абзац, который показывает, что ОП знает * почему * эти шаблоны существуют. Он просит провести сравнение между ними. – Quentin

+0

Оператор запятой не может быть перегружен, если один из операндов 'void'. – ecatmur

Смежные вопросы