std:: max() y std::min() no constexpr
Acabo de notar que el nuevo estándar define min(a,b)
y max(a,b)
sin constexpr
.
Ejemplos de 25.4.7, [alg.min.max]:
template<class T> const T& min(const T& a, const T& b);
template<class T> T min(initializer_list<T> t);
¿no es una lástima? Me hubiera gustado escribir
char data[ max(sizeof(A),sizeof(B)) ];
En lugar de
char data[ sizeof(A) > sizeof(B) ? sizeof(A) : sizeof(B) ];
char data[ MAX(sizeof(A),sizeof(B)) ]; // using a macro
Cualquier razón por la que los no pueden ser constexpr
?
5 answers
Actualización crítica
El siguiente análisis es incorrecto, porque confunde una cosa importante. En la siguiente declaración me perdí un detalle importante, que requiere una respuesta completamente diferente.
La referencia sin nombre
max
devuelve se referirá a ese operando.
El problema aquí es que sustitución de invocación de función es hecho en ese punto. Si la institución de invocación incluiría el lvalue a conversión de rvalue en ese glvalue que max
produce, todo estaría bien, porque la lectura de un glvalue que se refiere a un no temporal de duración de almacenamiento estático está bien durante el cálculo de la expresión constante. Pero como la lectura ocurre fuera de la sustitución de invocación de función, el resultado de la sustitución de invocación de función es un lvalue . El texto respectivo de la especificación dice
Una expresión constante de referencia es una constante del núcleo lvalue expresión que designa un objeto con duración de almacenamiento estático o una función.
Pero la referencia que devuelve max
produce un lvalue que designa un objeto de duración de almacenamiento no especificada. La sustitución de invocación de función es necesaria para producir una expresión constante , no simplemente una expresión constante core. Así que max(sizeof(A), sizeof(B))
no está garantizado que funcione.
El siguiente texto (más antiguo) debe leerse teniendo en cuenta lo anterior en cuenta.
No puedo ver ninguna razón en este momento por la que no quiera pegar un constexpr
allí. De todos modos, el siguiente código definitivamente es útil
template<typename T> constexpr
T const& max(T const& a, T const& b) {
return a > b ? a : b;
}
Contrariamente a lo que otras respuestas escriben, creo que esto es legal. No todas las instancias de max
deben ser funciones constexpr. La actual n3242 dice
Si la especialización de plantilla instanciada de una plantilla de función constexpr o una función miembro de una plantilla de clase fallaría satisfacer los requisitos para una función constexpr o un constructor constexpr, que la especialización no es una función constexpr o un constructor constexpr.
Si llama a la plantilla, la deducción de argumentos producirá una especialización de plantilla de función. Llamándolo se activará sustitución de invocación de función. Considere la siguiente llamada
int a[max(sizeof(A), sizeof(B))];
Primero hará una conversión implícita de los dos size_t
prvalues a los dos parámetros de referencia, vinculando ambos referencias a objetos temporales que almacenan su valor. El resultado de esta conversión es un glvalue para cada caso que se refiere a un objeto temporal (ver 4p3). Ahora la sustitución de invocación de función toma esos dos glvalues y sustituye todas las ocurrencias de a
y b
en el cuerpo de la función por esos glvalues
return (<glval.a>) > (<glval.b>) ? (<glval.a>) : (<glval.b>);
La condición requerirá conversiones lvalue a rvalue en estos glvalues, que son permitidos por 5.19p2
- un glvalue de tipo literal que se refiere a un objeto temporal no volátil inicializado con una expresión constante
La expresión condicional dará un glvalue al primer o segundo operando. La referencia sin nombre max
devuelve se referirá a ese operando. Y la conversión final de lvalue a rvalue que ocurre en la especificación de tamaño de dimensión de matriz será válida por la misma regla citada anteriormente.
Tenga en cuenta que initializer_list
actualmente no tiene funciones miembro constexpr
. Esto es una limitación conocida y se manejará después de C++0x, lo más probable es que esos miembros constexpr
.
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
2011-12-27 16:06:12
Std::min y std::max son constexpr en C++14, lo que obviamente significa que no hay una buena razón (en estos días) para no tenerlos constexpr. Problema resuelto: -)
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
2016-03-07 17:48:02
La inclusión de constexpr
versiones de std::min()
y std::max()
en C++14 demuestra que no hay ningún obstáculo fundamental para hacer (versiones de) estas funciones constexpr
. Parece que esto no se consideró lo suficientemente temprano cuando se agregó constexpr
a C++11.
Obviamente, para las versiones donde se proporciona una función de comparación, esa función debe ser constexpr
para que la expansión de la plantilla tenga éxito.
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
2016-07-14 08:11:22
min
y max
son solo expresiones constantes si las llamas con expresiones constantes como argumentos. Dado que están destinados a ser mucho más utilizables en general que eso, no puede hacer la declaración.
Esto es lo que Wikipedia dice sobre constexpr
(sin cursiva en el original). Sé que Wikipedia no es la referencia definitiva, pero creo que es correcta en este caso.
El uso de
constexpr
en una función impone limitaciones muy estrictas a lo que esa función puede hacer. Primero, el la función debe tener un retorno no nulo tipo. En segundo lugar, el contenido de la función debe ser de la forma: return expr. Tercero, expr debe ser una constante expresión, después del argumento sustitución. Esta expresión constante solo puede llamar a otras funciones definidas como constexpr, o puede utilizar otros variables de datos de expresión constante.
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
2011-04-09 14:33:11
Mi conjetura es que, en el caso general, operador
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
2011-04-09 13:01:55