Use compile-time constant if known

c++, compile-time, templates

Solution

Yes, you can do this. Using Johannes Schaub's trick, we can do the following:

template<typename T> 
constexpr typename std::remove_reference<T>::type makeprval(T && t) {
  return t;
}

#define constexpr_or_zero(e) (noexcept(makeprval(e)) ? (e) : 0)

const int cvalue = 7;
int ivalue = 7;

using type1 = std::integral_constant<int, constexpr_or_zero(cvalue)>;
using type2 = std::integral_constant<int, constexpr_or_zero(ivalue)>;

Here's a demo.

Problem

I have a value of some mystery type `T` (for this example, we can assume `T` is an integral type). I would like to use this value as a template argument in some template function (for this example, the argument to `std::integral_constant`). The trouble is that `T` might not be a constant type. If it isn't a constant type, I would like to default to `0` in my template function. If it is constant, however, I would like to use the value itself, since it is known. Currently, I have the following (non-compiling) code. ``` #include <type_traits> template <typename T> struct CompileTimeStuff { constexpr static int value(T arg) { return 0; } }; template <typename T> struct CompileTimeStuff<const T> { constexpr static int value(const T arg) { return (int)arg; } }; template <typename T> constexpr int magic_function(T arg) { return CompileTimeStuff<T>::value(arg); } const int cvalue = 7; int ivalue = 7; // This should be 7, since cvalue is constant and thus known at compile-time. typedef std::integral_constant<int, magic_function(cvalue)> type1; // Since ivalue is non-constant, this should take the default value of 0. typedef std::integral_constant<int, magic_function(ivalue)> type2; ``` Unfortunately, `g++` gives the following error. ``` templatestuff.cpp:28:58: error: the value of ‘ivalue’ is not usable in a constant expression typedef std::integral_constant<int, magic_function(ivalue)> type2; ``` The compiler doesn't like `ivalue` being used as a template argument, even though I never directly use its value in the instantiation.

Original source

Related problems