Is it possible to check if the value of const is known at compile time?

I am currently rewriting / expanding my C ++ utility library, taking into account the new features of C ++ 11. One of the new additions is the template class, which gives the maximum value of a set of numbers, I hope, at compile time.

template<typename T, T... Xs> class ConstMax { private: template<typename... Ts> static constexpr T Max(Ts... xs); template<typename Tx> static constexpr T Max(Tx x) { return x; } template<typename T1, typename T2, typename... Ts> static constexpr T Max(T1 x, T2 y, Ts... xs) { return y > x ? Max<T2, Ts...>(y, xs...) : Max<T1, Ts...>(x, xs...); } public: static const T Value = Max(Xs...); }; 

An example of using this class:

 int max = ConstMax<int, 1, 8, 66, 32, 90, 12, 33>::Value; 

Here is another example that might make it harder to check if ConstMax <...> :: Value was actually evaluated at compile time:

 template<typename... Ts> class Variant { public: static const size_t MaxValueSize = ConstMax<size_t, sizeof(Ts)...>::Value; }; 

The result is max = 90 . I went through this code with gdb, and there seems to be no function call executed during the max assignment.

My questions:

  • Is it ConstMax<...>::Value to assume that ConstMax<...>::Value always known at compile time?
  • Is there a way to check if constexpr functions / methods are executed at compile time?
  • I understand that members / methods / functions defined as constexpr are not necessarily evaluated at compile time, does the fact that Value is defined as static const change anything about it, or is it better for me to implement this particular case as a recursive template class?
+7
c ++ c ++ 11 constexpr
source share
2 answers
  • Is it safe to assume that ConstMax <...> :: The value is always known at compile time?

Yes, since it is initialized with a constant expression. But I would change Value as constexpr instead of const .

  1. Is there a way to check if constexpr functions / methods are executed at compile time?

Yes. Try using them in a constexpr expression. If this works, they are evaluated at compile time. If it does not compile, then it is not evaluated at compile time.

  1. I understand that members / methods / functions defined as constexpr are not necessarily evaluated at compile time, whether the fact that the value is defined as static const does something about this, or is it better for me to implement this particular case as a recursive boilerplate class?

If you use members in a constant expression, you force them to evaluate at compile time. Therefore, if you took care, I would simply evaluate them in constant expressions (via constexpr ).

+3
source share

To check if there is a constexpr expression (i.e. a constant expression), you can use a trait of type std::integral_constant as follows:

 #include <iostream> #include <type_traits> template<typename T, T... Xs> class ConstMax { template<typename... Ts> static constexpr T Max(Ts... xs); template<typename Tx> static constexpr T Max(Tx x) { return x;} template<typename T1, typename T2, typename... Ts> static constexpr T Max(T1 x, T2 y, Ts... xs) { return y > x ? Max<T2, Ts...>(y, xs...) : Max<T1, Ts...>(x, xs...); } public: static const T Value = Max(Xs...); }; int main() { std::cout << std::integral_constant<int, ConstMax<int, 1, 8, 66, 32, 90, 12, 33>::Value>::value << std::endl; } 

Live demo

If it is not constexpr , this will disrupt the compilation process.

+3
source share

All Articles