目前,我正在考虑新的C ++ 11功能,重写/扩展我的C ++实用程序库。其中一个新增功能是一个模板类,它可以在编译时提供一组数字的最大值。
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...);
};
此类的示例用法:
int max = ConstMax<int, 1, 8, 66, 32, 90, 12, 33>::Value;
这里有另一个例子可能会让我更难以验证在编译期间是否实际评估了ConstMax&lt; ...&gt; :: Value:
template<typename... Ts> class Variant
{
public:
static const size_t MaxValueSize = ConstMax<size_t, sizeof(Ts)...>::Value;
};
结果为max = 90
。我使用gdb逐步调试此代码,似乎在分配max。
我的问题:
ConstMax<...>::Value
吗?constexpr
函数/方法?constexpr
的成员/方法/函数不一定在编译期间进行评估,Value
被定义为static const
的事实是否改变了这一点,或者我是最好将此特定情况作为递归模板类实现?答案 0 :(得分:4)
要检查表达式是否为constexpr
(即常量表达式),您可以使用std::integral_constant
类型特征,如下所示:
#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;
}
如果它不是constexpr
,它将破坏编译过程。
答案 1 :(得分:3)
- 我可以安全地假设ConstMax&lt; ...&gt; :: Value在编译时始终是已知的吗?
醇>
是的,因为它是用常量表达式初始化的。但我将Value
修改为constexpr
而不仅仅是const
。
- 有没有办法检查constexpr函数/方法是否在编译时进行评估?
醇>
是。尝试在constexpr
表达式中使用它们。如果它有效,它们将在编译时进行评估。如果编译失败,那么它不会在编译时进行评估。
- 我理解定义为constexpr的成员/方法/函数不一定在编译期间进行评估,将Value定义为静态const的事实是否会改变这一点,或者我最好将此特定情况作为递归模板类实现?
醇>
如果在常量表达式中使用成员,则强制在编译时对它们进行求值。所以,如果你关心,我只需要确保用常量表达式评估它们(通过constexpr
)。