Разница между разбором void() и int()

прочитав о самом неприятном разборе, я немного поэкспериментировал и нашел эту программу. Есть две очень похожие линии. Один из них дает предупреждения как в g++7, так и в clang++-3.9, другой-нет.

int main() {
  void(); // no warning
  int(); // warning: statement has no effect
}

во второй строке объект, построенный по умолчанию типа int создается и немедленно уничтожается, таким образом, не используется. Но что происходит в первой строке? Если он был проанализирован таким же образом, это должно быть ошибкой, потому что создание объекта типа незаконно void. С другой стороны, это также не похоже на объявление функции.

2 ответов


нет никакой разницы в разборе. Оба случая охватываются простой-тип-описатель за которым следуют необязательные скобки expression-list.

семантическое значение указано в C++17 (N4659) [expr.тип.conv] / 2:

если тип cv void и инициализатор (), выражение является prvalue указанного типа, который не выполняет инициализацию. В противном случае выражение является prvalue указанный тип, объект результата которого инициализируется инициализатором напрямую.

это конкретно говорит о том, что void() является prvalue типа void.

теперь, я уверен, что это не предназначены что prvalue типа void является незаконным, так как это обычное явление, например (void)x; или вызов функции void!

но я не могу найти, где в стандарте говорится, что временная материализация должна быть подавлена для void prvalues. Класс.temporary] / 2, по-видимому, говорит, что выражение отброшенного значения всегда материализует временное; и это ошибка материализовать prvalue неполного типа. Возможно, это дефект стандарта.


разница в предупреждении о "неиспользуемом значении", вероятно, потому, что неиспользуемое значение типа void является обычным явлением, и было бы не полезно предупреждать об этом.


Это is проанализировано таким же образом.

предупреждения не поступают от парсера. Они возникают при семантическом анализе. SA заметил, что значение было создано уничтожено int(); без чтения или записи.

на void case, нет значения, поэтому нет предупреждения.