¿Qué es const void?

89

La descripción de std::is_voidestablece que:

Proporciona el valor de la constante del miembro que es igual a verdadero, si T es del tipo void, const void, volatile void o const volatile void.

Entonces, ¿qué podría ser const void, o un volatile void?

Esta respuesta indica que el const voidtipo de retorno no sería válido (sin embargo, se compila en VC ++ 2015)

const void foo() { }

Si, por norma, const voidno es válido (VC es incorrecto), ¿qué es const void?

Ajay
fuente
15
La respuesta a la que enlaza no dice que sería inválida, dice que sería "sin sentido", lo que yo interpretaría como que "no ofrece ningún beneficio voidsin ella const".
@hvd, la respuesta indica que el compilador debe advertir / error sobre dicha calificación. Por eso, supongo que el estándar C ++ no permite calificaciones convoid
Ajay
2
La respuesta indica que el compilador debe advertir sobre dicha calificación, no menciona un error y un error sería incorrecto. Ese comentario se trata solo de la calidad de la implementación, no de la conformidad, pero puedo entender que eso no está del todo claro a partir del comentario en sí.
@Ajay el estándar no especifica que debería haber una advertencia cuando usa código sin sentido. Fue una decisión de gcc para darle una pista adicional de que este código no hace nada. Pero VC no se equivoca de ninguna manera.
user1942027
3
@Ajay La respuesta dice que clang da una advertencia, y que, en opinión del autor, otros compiladores deberían hacerlo. Si el estándar no lo permitiera, sería un error, no una advertencia.
molbdnilo

Respuestas:

94

const voides un tipo al que puede formar un puntero. Es similar a un puntero vacío normal, pero las conversiones funcionan de manera diferente. Por ejemplo, a const int*no se puede convertir implícitamente en a void*, pero se puede convertir implícitamente en a const void*. Del mismo modo, si tiene un, const void*no puede static_casthacerlo a un int*, pero puede static_casthacerlo a un const int*.

const int i = 10;
void* vp = &i;                           // error
const void* cvp = &i;                    // ok
auto ip = static_cast<int*>(cvp);        // error
auto cip = static_cast<const int*>(cvp); // ok
Benjamin Lindley
fuente
4
Si bien su respuesta es buena, no indica la razón de const void, pero se trata de punteros vacíos y no vacíos [con (no) constancia].
Ajay
26
@Ajay: No estoy de acuerdo. A const void*es la única razón por la que alguna vez verías const void. Se puede pasar como un argumento de plantilla, pero ese tipo de argumento solo se instanciará con un *al final.
Benjamin Lindley
@BenjaminLindley También puede ver const voiden la pregunta formulada por un abogado de idiomas
cpplearner
3
@Ajay: En algún momento, esta pregunta se convierte en una cuestión de filosofía. La "razón" de const voides que se pueden hacer todos los tipos en C ++ const. "Existe" de la misma manera que voidexiste. La respuesta de @Benjamin Lindley explica qué es cuando lo ve y cómo lo usa.
Chris Beck
23

Como void, const voides un tipo vacío. Sin embargo, si const voides un tipo de retorno , no consttiene sentido (¡aunque es legal!), Porque [expr] / 6 :

Si un prvalue tiene inicialmente el tipo " cv T ", donde Tes un tipo cv-no calificado, sin clase, sin matriz, el tipo de expresión se ajusta aT antes de cualquier análisis adicional.

Sin embargo, es un tipo válido en sí mismo y ocurre, por ejemplo , en funciones de biblioteca estándar C , donde se usa para garantizar la corrección constante de los punteros de los argumentos: int const*no se puede convertir a void*, pero void const*.

Columbo
fuente
const voidya que un tipo de retorno afecta al tipo de función, por lo que no es completamente insignificante.
cpplearner
1
@cpplearner Excepto que lo es en todos los sentidos prácticos, porque ni la firma de la función ni el tipo de llamada a ella se ven afectados.
Columbo
Bueno, puede cambiar la firma de una plantilla de función. +1 sin embargo
cpplearner
@cpplearner Bastante justo, sin embargo, todavía es una pérdida de pulsaciones de teclas.
Columbo
Normalmente vemos: const int * no puede ir a void *, pero const void *.
mgouin
18

Los tipos pueden ser el resultado de plantillas; una plantilla puede declarar const Ty crear una instancia con Tcomo void.

La respuesta vinculada es engañosa, o más bien, limitada en vista de que se refiere al caso especial de un tipo sin plantilla, e incluso entonces const voidpodría no tener sentido , pero es un código válido .

DevSolar
fuente