¿Es ilegal invocar una función std:: bajo el estándar?


Todas las citas son de N3797.

4/3 [conv]

Una expresión e puede ser convertido implícitamente a un tipo T si y solo si la declaración T t = e; está bien formado, para algunas variables temporales inventadas t

Esto implica que ninguna expresión puede convertirse implícitamente a void, ya que void t=e es ilegal para todas las expresiones e. Esto es incluso cierto si e es una expresión de tipo void, como void(3).

So una expresión de tipo void no se puede convertir implícitamente void.

Que nos lleva a: {[27]]}

20.9.2/2 Requisitos [func.requerir]

Definir INVOCAR (f, t1, t2, ..., tN, R) como INVOCAR (f, t1, t2, ..., tN) convertido implícitamente a R .

En resumen, INVOKE(f, t1, t2, ..., tN, R) nunca es válido cuando R es void, ya que nada (incluido void) se puede convertir implícitamente a void.

Como resultado de esto, todos std::function<void(Args...)> tienen la propiedad !*this y por lo tanto no se puede llamar, ya que los únicos constructores que no tienen !*this como postcondición (o no copian dicho estado de otro function del mismo tipo) requieren Callable de uno de los parámetros.

20.9.11.2/7 plantilla de Clase función [func.envolver.func]

Requiere: F será CopyConstructible . f será Exigible ( 20.9.11.2 ) para tipos de argumentos ArgTipos y tipo de retorno R . El constructor de copia y destructor de Un no lanzará excepciones.

20.9.11.2/2 plantilla de Clase función [func.envolver.func]

Un objeto invocable f de tipo F ser Invocable para tipos de argumentos ArgTipos y tipo de retorno R si la expresión- sion INVOCAR (f, declval ()..., R) , considerado como un operando no evaluado (Cláusula 5 ), está bien formar ( 20.9.2 ).

Como se demostró anteriormente, no hay Callable expresiones para std::function<void(Args...)>.

Si de alguna manera se encontrara tal std::function<void(Args...)>, invocar operator() estaría mal formado:

Invocación [func .envolver.func.inv]

Efectos: INVOCAR (f, std:: forward (args)..., R) ( 20.9.2 ), donde f es el objetivo ob- ject ( 20.9.1 ) de *este .

Como INVOKE(f, std::forward<ArgTypes>(args)..., void) está mal formado para todos los argumentos y f.

¿Es correcta esta línea de razonamiento?

Author: Yakk - Adam Nevraumont, 2014-08-20

1 answers

Sí, su análisis es correcto; llegué a la misma conclusión aquí.

Según Daniel Kruegler, este problema debería aparecer en la lista de defectos de la biblioteca después del siguiente correo:

Ya se ha enviado un problema de biblioteca correspondiente, pero no aún visible en la lista de problemas.

Esperemos que una vez que se haga visible también tendremos una respuesta concluyente a si es permisible construir un std::function con signature returning void pasando un callable con signature returning non-void ( Usando `std::function ` to call non-void function ).


Actualización: esto se introdujo como LWG 2420, que se resolvió a favor de special-casing void return type to static_cast el resultado de la función invocada a void. Esto significa que un no-void retornable puede ser el objetivo de un std::function<void(...)>. LWG2420 se aplicó como corrección post-publicación a C++14; mientras tanto, todos los compiladores que conozco aplican efectivamente este comportamiento como una extensión en el modo C++11.

 16
Author: ecatmur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:14:57