When does the constexpr function get evaluated at compile time?

Since it is possible that a function declared as constexpr can be called at run time, by what criteria does the compiler decide whether to evaluate it at compile time or at run time?

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; } 

In this case, I am not aware at compile time, which is probably the reason that the compiler treats POW () as a regular function that is called at runtime. However, this dynamic, as far as it can be convenient, has some impractical consequences. For example, can there be a case where I would like the compiler to compute the constexpr function at compile time, when the compiler decides to treat it as a normal function, and also when it would work at compile time? Are there any known errors?

+46
c ++ c ++ 11 runtime constexpr compile-time
Jan 09 '13 at 23:18
source share
2 answers

constexpr functions will be evaluated at compile time, when all its arguments are constant expressions, and the result is also used in the constant expression. A constant expression can be a literal (e.g. 42 ), a non-type template argument (e.g. N in template<class T, size_t N> class array; ), an enum element declaration (e.g. Blue in enum Color { Red, Blue, Green }; ), another declared variable constexpr, etc.

They can be evaluated when all its arguments are constant expressions, and the result is not used in a constant expression, but it depends on the implementation.

+68
Jan 09 '13 at 23:25
source share

The function must be evaluated at compile time when a constant expression is required.

The easiest way to guarantee this is to use the value of constexpr or 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; 

or

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

or

 #define POW_C(base, power) (std::integral_constant<decltype(POW((base), (power)), POW((base), (power))>::value) std::cout << POW_C(63, 2) << std::endl; 

or

 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
Jan 09 '13 at 23:24
source share



All Articles