¿Devolver un vacío?


No entiendo por qué este código compila sin error:

#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;
}

¿Está bien de acuerdo con el estándar, o es una tolerancia del compilador?

Author: Vincent, 2013-12-09

3 answers

Esto parece válido para el borrador del estándar C++11, si miramos la sección 5.2.3 Conversión explícita de tipos (notación funcional) párrafo 2 dice ( énfasis mío):

La expresión T () , donde T es un especificador de tipo simple o typename-specifier for a non-array complete object type or the tipo void , crea un prvalue de la tipo especificado, cuyo valor es el producido por inicialización de valores (8.5) un objeto de tipo T; no se realiza inicialización para el vacío() caso.[...]

La redacción es bastante similar pre C++11 también.

Esto está bien en un constexpr a pesar de que la sección 7.1.5 párrafo 3 dice:

La definición de una función constexpr deberá satisfacer lo siguiente: limitaciones:

, E incluye esta viñeta:

Su tipo de retorno será un literal tipo;

Y void no a literal{[9] {} en[8]}C++11 por la sección 3.9 párrafo 10, pero si luego miramos el párrafo 6 se da una excepción que se ajusta a este caso, se dice:

Si la especialización de plantilla instanciada de una función constexpr plantilla o función miembro de una plantilla de clase no podría satisfacer los requisitos para una función constexpr o un constructor constexpr, esa especialización es no es una función constexpr o constexpr constructor. [Nota: Si la función es una función miembro, todavía ser const como se describe a continuación. - end note] If no specialization of la plantilla daría una función constexpr o constexpr constructor, el programa está mal formado; no se requiere diagnóstico.

Como Casey señaló en el C++14 draft standard void es un literal , esta es la sección 3.9 Tipos párrafo 10 dice:

Un tipo es un tipo literal si es:

E incluye:

- nulo; o

 25
Author: Shafik Yaghmour,
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 10:27:21

Ver la respuesta de @Shafik Yaghmour para la información completa.

El siguiente párrafo prohíbe esto para no plantillas (7.1.5(3)):

La definición de una función constexpr deberá satisfacer las siguientes restricciones:

  • [...]

  • Su tipo de retorno será un tipo literal o una referencia al tipo literal

Para elaborar, un tipo literal se define en 3.9 (10) como un tipo escalar o una composición de objetos de tipo literal en una matriz o estructura. void no es un tipo escalar por 3.9 (9).

 6
Author: filmor,
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
2013-12-09 19:17:02

Su función devuelve el valor de void(), no está regresando de una función void per se. Está devolviendo un valor NULL. Lo que estás haciendo es equivalente a esto:

void f() { return void(); }

Esto devuelve un valor void, el único valor void. no puede devolver nada más de una función void porque será de un tipo diferente.

 1
Author: user3084096,
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
2013-12-10 00:30:47