Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Currently I am rewriting/extending my C++ utility library taking new C++11 features into account. One of the new additions is a template class which gives the maximum value of a set of numbers, hopefully 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 use of this class:

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

Here another example which might make it harder to verify if ConstMax<...>::Value was actually evaluated during compile time:

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

Which results in max = 90. I stepped trough this code using gdb and it seems there is no function call executed during the assignment of max.

My questions:

  1. Can I safely assume that ConstMax<...>::Value is always known at compile time?
  2. Is there a way to check if constexpr functions/methods are evaluated at compile time?
  3. I understand members/methods/functions defined as constexpr are not necessarily evaluated during compile time, does the fact that Value is defined as being static const change anything about this or am I better off implementing this specific case as a recursive template class?
like image 820
Charlie Avatar asked May 25 '16 14:05

Charlie


People also ask

Is const evaluated at compile time?

Constant expressions. Certain forms of expressions, called constant expressions, can be evaluated at compile time. In const contexts, these are the only allowed expressions, and are always evaluated at compile time.

Is const compile time?

Difference between Run-time and Compile-time constantsA compile-time constant is a value that is computed at the compilation-time. Whereas, A runtime constant is a value that is computed only at the time when the program is running. 2.

Does constexpr imply const?

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. Such variables and functions can then be used where only compile time constant expressions are allowed. constexpr implies const.

Is const compile time C++?

A const variable is a compile-time constant if its initializer is a constant expression. Because the initialization values of x and y are constant expressions, x and y are compile-time constants. This means x + y is also constant expression.


2 Answers

To check if an expression is constexpr (i.e., constant expression) you could use std::integral_constant type trait 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's not constexpr it will break the compilation process.

like image 135
101010 Avatar answered Oct 16 '22 04:10

101010


  1. Can I safely assume that ConstMax<...>::Value is always known at compile time?

Yes, since it's initialized with a constant expression. But I'd modify Value to be constexpr instead of just const.

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

Yes. Try using them in a constexpr expression. If it works, they're being evaluated at compile time. If it fails to compile, then it's not being evaluated at compile time.

  1. I understand members/methods/functions defined as constexpr are not necessarily evaluated during compile time, does the fact that Value is defined as being static const change anything about this or am I better off implementing this specific case as a recursive template class?

If you use the members in a constant expression, you're forcing them to be evaluated at compile time. So if you cared, I'd just make sure to evaluate them in constant expressions (via constexpr).

like image 36
Cornstalks Avatar answered Oct 16 '22 03:10

Cornstalks