如果已知,则使用编译时常量
Use compile-time constant if known
我有一个神秘类型的值 T
(对于这个例子,我们可以假设 T
是一个整数类型)。我想在一些模板函数中使用这个值作为模板参数(对于这个例子,std::integral_constant
的参数)。问题是 T
可能不是常量类型。如果它不是常量类型,我想在我的模板函数中默认为 0
。但是,如果它是常数,我想使用该值本身,因为它是已知的。
目前,我有以下(非编译)代码。
#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;
不幸的是,g++
给出了以下错误。
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;
编译器不喜欢 ivalue
被用作模板参数,即使我从未在实例化中直接使用它的值。
是的,你可以做到这一点。使用 Johannes Schaub's trick,我们可以执行以下操作:
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)>;
我有一个神秘类型的值 T
(对于这个例子,我们可以假设 T
是一个整数类型)。我想在一些模板函数中使用这个值作为模板参数(对于这个例子,std::integral_constant
的参数)。问题是 T
可能不是常量类型。如果它不是常量类型,我想在我的模板函数中默认为 0
。但是,如果它是常数,我想使用该值本身,因为它是已知的。
目前,我有以下(非编译)代码。
#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;
不幸的是,g++
给出了以下错误。
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;
编译器不喜欢 ivalue
被用作模板参数,即使我从未在实例化中直接使用它的值。
是的,你可以做到这一点。使用 Johannes Schaub's trick,我们可以执行以下操作:
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)>;