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.