Considere la siguiente función en línea:
// Inline specifier version
#include<iostream>
#include<cstdlib>
inline int f(const int x);
inline int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
y la versión equivalente constexpr:
// Constexpr specifier version
#include<iostream>
#include<cstdlib>
constexpr int f(const int x);
constexpr int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
Mi pregunta es: ¿el constexpr
especificador implica el inline
especificador en el sentido de que si se pasa un argumento no constante a una constexpr
función, el compilador intentará inline
la función como si el inline
especificador se pusiera en su declaración?
¿El estándar C ++ 11 garantiza eso?
inline
especificador. (O tal vez entendí mal tu fraseo.)inline
especificador ya no tiene nada que ver con el inlininginline
está directamente relacionada con el inlining. Entonces no, elconstexpr
especificador no implica elinline
especificador en ese sentido, ya que ese sentido no existe.Respuestas:
Sí ([dcl.constexpr], §7.1.5 / 2 en el estándar C ++ 11): "las funciones constexpr y los constructores constexpr están implícitamente en línea (7.1.2)".
Sin embargo,
inline
tenga en cuenta que el especificador realmente tiene muy poco efecto (si es que tiene alguno) sobre si es probable que un compilador expanda una función en línea o no. Sin embargo, sí afecta la regla de una definición, y desde esa perspectiva, el compilador debe seguir las mismas reglas para unaconstexpr
función comoinline
función.También debo agregar que independientemente de
constexpr
lo que implicainline
, las reglas paraconstexpr
funciones en C ++ 11 requerían que fueran lo suficientemente simples como para que a menudo fueran buenos candidatos para la expansión en línea (la excepción principal son las que son recursivas). Desde entonces, sin embargo, las reglas se han vuelto progresivamente más flexibles, por lo queconstexpr
pueden aplicarse a funciones sustancialmente más grandes y complejas.fuente
constexpr
funciones no causarán generación de código en absoluto ...constexpr
funciones de @KerrekSB se evalúan potencialmente en tiempo de compilación. Sin embargo, el estándar C ++ 14 está plagado de algunos que muy probablemente se llamarán en tiempo de ejecución. Por ejemplo:std::array<T,N>::at
constexpr
no implicainline
para variables no estáticas (variables en línea de C ++ 17)Si bien
constexpr
implicainline
para funciones, no tiene ese efecto para variables no estáticas, considerando las variables en línea de C ++ 17.Por ejemplo, si toma el ejemplo mínimo que publiqué en: ¿Cómo funcionan las variables en línea? y elimine el
inline
, dejando soloconstexpr
, entonces la variable obtiene múltiples direcciones, que es lo principal que evitan las variables en línea.constexpr
Sin embargo, las variables estáticas son implícitamente estáticas.Ejemplo mínimo que
constexpr
implicainline
para funcionesComo se menciona en: https://stackoverflow.com/a/14391320/895245, el efecto principal de
inline
no es inline sino permitir múltiples definiciones de una función, cita estándar en: ¿Cómo puede un archivo de encabezado C ++ incluir la implementación?Podemos observar eso jugando con el siguiente ejemplo:
main.cpp
notmain.hpp
notmain.cpp
Compilar y ejecutar:
Si eliminamos
inline
deshared_func
, el enlace fallaría con:porque el encabezado se incluye en varios
.cpp
archivos.Pero si reemplazamos
inline
conconstexpr
, entonces funciona de nuevo, porqueconstexpr
también implicainline
.GCC implementa eso al marcar los símbolos como débiles en los archivos de objeto ELF: ¿Cómo puede un archivo de encabezado C ++ incluir la implementación?
Probado en GCC 8.3.0.
fuente
constexpr
todavía está en línea. cppreference.com : una variable miembro estática (pero no una variable de ámbito de espacio de nombres) declaradaconstexpr
es implícitamente una variable en línea.