Подтвердить что ты не робот

Возвращение пустоты?

Я не понимаю, почему этот код компилируется без ошибок:

#include <iostream>

template <class T>
struct Test
{
    static constexpr T f() {return T();} 
};

int main()
{
    Test<void> test;
    test.f(); // Why not an error?
    return 0;
}

Хорошо ли в соответствии со стандартом, или это допуск к компилятору?

4b9b3361

Ответ 1

Это выглядит так: черновик С++ 11, если мы посмотрим на раздел 5.2.3 Явное преобразование типа (функциональная нотация) в пункте 2 говорится (основное внимание):

выражение T(), где T - спецификатор простого типа или typename-specifier для типа объекта без массива или (возможно, cv-qualified) тип void, создает prvalue указанный тип, значение которого создается инициализацией значения (8.5) объект типа T; не выполняется инициализация для void() случай. [...]

формулировка довольно похожа на pre С++ 11.

Это нормально в constexpr, хотя раздел 7.1.5 paragraph 3 говорит:

Определение функции constexpr должно удовлетворять следующему Ограничения:

и включает эту марку:

его тип возврата должен быть литеральным типом;

а void не является литералом в С++ 11 в соответствии с параграфом 3.9 раздела 10, но если мы посмотрим на пункт 6, он даст исключение, соответствующее этому случаю, он говорит:

Если заданная шаблонная специализация функции constexpr шаблон или функция-член шаблона класса не смогут удовлетворить требования к функции constexpr или конструктору constexpr, эта специализация не является функцией constexpr или constexpr конструктор. [Примечание: если функция является функцией-членом, она будет все еще будет const, как описано ниже. -end note] Если никакая специализация шаблон даст функцию constexpr или constexpr конструктор, программа плохо сформирована; не требуется диагностика.

Как Кейси отметил в С++ 14 draft standard void is буква, это раздел 3.9. В параграфе 10 говорится:

Тип - это буквальный тип, если он:

и включает в себя:

- void; или

Ответ 2

См. @Shafik Yaghmour ответ за полную информацию.

Следующий абзац запрещает это для не-шаблонов (7.1.5 (3)):

Определение функции constexpr должно удовлетворять следующим ограничениям:

  • [...]

  • его возвращаемый тип должен быть литеральным типом или ссылкой на тип литерала

Чтобы уточнить, тип литерала определен в 3.9 (10) как скалярный тип или состав объектов литерала типа в массиве или структуре. void не является скалярным типом по 3,9 (9).

Ответ 3

Ваша функция возвращает значение void(), вы не возвращаетесь из функции void как таковой. Вы возвращаете значение NULL. То, что вы делаете, эквивалентно этому:

void f() { return void(); }

Возвращает значение void, единственное значение void. вы не можете вернуть ничего из функции void, потому что это будет другой тип.