¿Cuándo se evalúa una función constexpr en tiempo de compilación?


Dado que es posible que una función declarada como constexpr pueda ser llamada durante el tiempo de ejecución, ¿bajo qué criterios decide el compilador si computarla en tiempo de compilación o durante el tiempo de ejecución?

template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
    return (expo != 0 )? base * POW(base, expo -1) : 1;
}

int main(int argc, char** argv)
{
    int i = 0;
    std::cin >> i;

    std::cout << POW(i, 2) << std::endl;
    return 0;
}

En este caso, i es desconocido en tiempo de compilación, que es probablemente la razón por la que el compilador trata a POW() como una función regular que se llama en tiempo de ejecución. Sin embargo, esta dinámica, por conveniente que pueda parecer, tiene algunas implicaciones poco prácticas. Por ejemplo, ¿podría haber ¿un caso en el que me gustaría que el compilador calculara una función constexpr durante el tiempo de compilación, donde el compilador decide tratarla como una función normal en su lugar, cuando también habría funcionado durante el tiempo de compilación? ¿Hay alguna dificultad común conocida?

Author: Byzantian, 2013-01-10

2 answers

constexpr functions será evaluada en tiempo de compilación cuando todos sus argumentos son expresiones constantes y el resultado se utiliza también en una expresión constante. Una expresión constante podría ser un literal (como 42), un argumento de plantilla sin tipo (como N en template<class T, size_t N> class array;), una declaración de elemento enum (como Blue en enum Color { Red, Blue, Green };, otra variable declarada constexpr, y así sucesivamente.

They might be evaluated when all its arguments are constant expressions and the result es no usado en una expresión constante, pero eso depende de la implementación.

 74
Author: K-ballo,
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-01-11 17:28:36

La función tiene que ser evaluada en tiempo de compilación cuando se necesita una expresión constante.

El método más simple para garantizar esto es usar un valor constexpr, o std::integral_constant:

constexpr auto result = POW(i, 2); // this should not compile since i is not a constant expression
std::cout << result << std::endl;

O:

std::cout << std::integral_constant<int, POW(i, 2)>::value << std::endl;

O

#define POW_C(base, power) (std::integral_constant<decltype(POW((base), (power)), POW((base), (power))>::value)

std::cout << POW_C(63, 2) << std::endl;

O

template<int base, int power>
struct POW_C {
  static constexpr int value = POW(base, power);
};

std::cout << POW_C<2, 63>::value << std::endl;
 17
Author: Pubby,
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-01-09 23:45:42