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

Построение типа пустоты?

Мне был предоставлен фрагмент кода, который использует void() в качестве аргумента. Код не компилируется... очевидно?

Можно ли создать экземпляр типа void? Я полагал, что ответа нет, за исключением void*. Например:

  • Написание ошибок функции void askVoid(void param) {}:

Параметр может не иметь тип void

  1. Написание функции void askNaught() {} и вызов ее с помощью askNaught (void()) `errors:

ошибка C2660: takeNaught: функция не принимает 1 аргумент

  1. Написание темплатной функции template <typename T> void takeGeneric(T param) {} и вызов ее с ошибками takeGeneric(void()):

ошибка C2893: не удалось специализировать шаблон функции void takeGeneric(T)

  1. Объявление void voidType ошибок:

Неполный тип недопустим

  1. Объявление auto autoVoid = void() ошибок:

Невозможно вывести тип auto

  1. Объявление void* voidPtr работает нормально, но remove_pointer_t<decltype(voidPtr)> decltypeVoid ошибки:

ошибка C2182: decltypeVoid: незаконное использование типа void

Что, верно? В С++ нет места для void()? Это просто плохой код, который мне дал, не так ли?

4b9b3361

Ответ 1

Выражение void() является prvalue типа void и может использоваться везде, где может использоваться такое выражение, которое [basic.fundamental]/9 содержит список:

  • Как выражение-выражение: void();
  • В качестве второго или третьего операнда условного оператора: true ? throw 1 : void()
  • В качестве операнда оператора запятой: ++it1, void(), ++it2
  • В качестве операнда decltype или noexcept: using my_void = decltype(void()); static_assert(noexcept(void()), "WAT");
  • В выражении return возвращаемой функции (возможно, cv-qualified) void: const void f() { return void(); }
  • В качестве операнда явного преобразования в (возможно, с квалификацией) void: static_cast<const void>(void())

Выражение типа void также может использоваться как операнд typeid, но void() в частности будет анализироваться как тип, а не выражение в этом контексте.

Ответ 2

Вы можете принять параметр функции void() как:

void test(void()) { ... }

Расширяется до:

void test(void (*)())

Это указатель на метод, который возвращает void и не принимает никаких аргументов.

Полный пример:

void abc() {}
void test(void()) { }

int main() {
    test(abc);
}

Ответ 3

С++ (и я говорю, что С++, а не C) позволяет (§6.6.3 запятая 2) с возвратным типом void для возврата a void, то есть:

void foo() { return void(); }

Но заметьте, что он не создает временную void!

Ответ 4

Вы можете использовать void() как вызываемый тип, так как пример std::function<void()> f; является допустимым оператором.

Кроме того, как из 8.3.5/4:

Список параметров, состоящий из одного неназванного параметра не зависящего от типа типа void, эквивалентен списку пустых параметров.

Это означает, что это действительно:

template<typename T>
struct F;

template<typename R, typename... A>
struct F<R(A...)> { };

int main () {
   F<void(void)> s;
}

Здесь вы не создаете экземпляр типа void, но используете его (скажем) как список параметров вызываемого типа.

Не уверен, что это ответ на ваш вопрос, я не понимаю, на самом деле вопрос.

Ответ 5

В С++ нет места для void()?

В качестве выражения в С++ допустимо void().

Из стандарта $5.2.3/2 Explicit type conversion (functional notation) [expr.type.conv]:

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

Из cppreference.com:

new_type()

Если new_type - тип объекта, объект инициализируется значением; в противном случае инициализация не выполняется. Если new_type (возможно cv-qualified) void, выражение является void prvalue.