2012-09-09 17 views
7

Considere el siguiente código:¿Por qué constexpr funciona con plantillas?

template<typename T> 
constexpr inline T fma(T a, T b, T c) 
{ 
    return a * b + c; 
} 

Esto compila bien. Pero ¿por qué? En teoría, las funciones constexpr solo pueden llamar a otras funciones constexpr. Sin embargo, no hay garantía de que los operadores sean funciones constestables. Por ejemplo, digamos que tengo algún tipo con la siguiente interfaz:

Los operadores + y * no son constexpr. Si escribo el siguiente código:

fma(someType(), someType(), someType()); 

Debe dejar de compilar porque una función constexpr está llamando a funciones no constexpr. Pero compila bien. ¿Por qué es esto?

Estoy usando el compilador G ++ de MinGW con la opción -std = C++ 0x.

+0

Para un ejemplo donde es descaradamente obvio que no puede optimizar todo, compila con GCC 4.7.1 cuando se ingresan los tres argumentos y se imprime el resultado: http://ideone.com/aBRPU – chris

+0

intente esto: 'constexpr someType dummy = fma (someType(), someType(), someType());';) – mfontanini

+0

Ooh, acabo de encontrar en el estándar que las funciones 'constexpr' están implícitamente en línea, si eso te ahorra espacio. – chris

Respuesta

5

Si llama a una función constexpr utilizando expresiones no constantes como sus argumentos, la función se ejecuta en tiempo de ejecución.

Si hace esto:

constexpr someType dummy = fma(someType(), someType(), someType()); 

se producirá un error, ya que están obligando a los resultados que se almacena en un tipo constexpr. Eso no se puede hacer en tiempo de compilación, por lo tanto, obtienes un error de compilación.

Tenga en cuenta que este haría el trabajo si ya ha proporcionado tanto un constructor y una constexprconstexproperator+/* en someType.

0

Dado que las plantillas se comprueban principalmente en busca de errores de uso, solo cuando se utiliza con un tipo con operadores no constexpr se producirá un error.

5

Desde la sección 7.1.5.6 de la norma C++ 11:

If the instantiated template specialization of a constexpr function template or member function of a class 
template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that 
specialization is not a constexpr function or constexpr constructor. [ Note: If the function is a member 
function it will still be const as described below. — end note ] If no specialization of the template would 
yield a constexpr function or constexpr constructor, the program is ill-formed; no diagnostic required. 

Esto significa que una plantilla de función constexpr degrada a una función no constexpr si se crea una instancia con los parámetros de plantilla que hacen que no sea una función constexpr válida.

Si no fuera una función constexpr válida independientemente de los parámetros de plantilla que le haya dado, entonces el compilador puede quejarse, pero no tiene por qué.

Cuestiones relacionadas