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

Нельзя ли ссылаться на std:: function <void (Args...)> по стандарту?

Все цитаты из N3797.

4/3 [conv]

Выражение е возможно неявно преобразованный к типу T тогда и только тогда, когда декларация T t = e; хорошо сформирована, для некоторой изобретенной временной переменной т

Это означает, что выражение не может быть неявно преобразовано в void, поскольку void t=e является незаконным для всех выражений e. Это даже верно, если e является выражением типа void, например void(3).

Таким образом, выражение типа void не может быть неявно преобразовано в void.

Это приводит нас к:

20.9.2/2 Требования [func.require]

Define ВЫЗОВ (f, t1, t2,..., tN, R) в виде ВЫЗОВ (f, t1, t2,..., tN) неявно преобразованный в р.

Короче говоря, INVOKE(f, t1, t2, ..., tN, R) никогда не действует, если R равно void, поскольку ничто (включая void) не может быть неявно преобразовано в void.

В результате этого все std::function<void(Args...)> имеют свойство !*this и поэтому не могут быть вызваны как единственные конструкторы, не имеющие !*this в качестве постусловия (или не копировать такое состояние из другого function того же типа) требуют Callable одного из параметров.

20.9.11.2/7 Шаблон класса функция [Func.wrap.func]

Требуется: F должен быть CopyConstructible, е должны быть Подтверждаемыми ( 20.9.11.2 ) для типов аргументов ArgTypes и тип возврата р, Конструктор копирования и деструктор не должны исключать исключения.

20.9.11.2/2 Шаблон класса функция [Func.wrap.func]

Вызываемый объект е типа F является подлежащий выкупу для типов аргументов ArgTypes и тип возврата р если выражение Sion ВЫЗОВ (f, declval()..., R), рассматриваемый как неоцениваемый операнд (пункт 5), хорошо сформированный ( 20.9.2).

Как показано выше, для std::function<void(Args...)> нет выражений Callable.

Если каким-то образом найденный std::function<void(Args...)>, где был найден, вызывается operator():

вызов [func.wrap.func.inv]

Эффекты: ВЫЗОВ (f, std:: forward (args)..., R) ( 20.9.2), где е является целевым ject ( 20.9.1 ) *это.

как INVOKE(f, std::forward<ArgTypes>(args)..., void) плохо сформирован для всех аргументов и f.

Является ли эта линия рассуждения звуком?

4b9b3361

Ответ 1

Да, ваш анализ правильный; Я пришел к тому же выводу здесь.

По словам Даниэля Крюглера, этот вопрос должен появиться в списке дефектов библиотеки после следующей рассылки:

Соответствующая проблема с библиотекой уже отправлена, но не но видимый в списке проблем.

Надеемся, что когда это станет видимым, мы также получим окончательный ответ на то, можно ли построить std::function с сигнатурой, возвращающей void, передавая вызываемый код с возвращаемой сигнатурой не-void (Использование` std:: function < void (...) > `для вызова функции non-void).


Обновление: это было введено как LWG 2420, которое было разрешено в отношении типа возврата void с особым корпусом static_cast результат вызываемой функции void. Это означает, что вызываемым возвращаемым не void может быть цель std::function<void(...)>. LWG2420 был применен в качестве поправки после публикации к С++ 14; Между тем, все компиляторы, которые я знаю, эффективно применяют это поведение как расширение в режиме С++ 11.