是否可以检查编译时是否知道const值?

时间:2016-05-25 14:37:01

标签: c++ c++11 constexpr

目前,我正在考虑新的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。

期间没有执行函数调用

我的问题:

  1. 我可以安全地假设在编译时始终知道ConstMax<...>::Value吗?
  2. 有没有办法检查在编译时是否评估constexpr函数/方法?
  3. 我理解定义为constexpr的成员/方法/函数不一定在编译期间进行评估,Value被定义为static const的事实是否改变了这一点,或者我是最好将此特定情况作为递归模板类实现?

2 个答案:

答案 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;   
}

Live Demo

如果它不是constexpr,它将破坏编译过程。

答案 1 :(得分:3)

  
      
  1. 我可以安全地假设ConstMax&lt; ...&gt; :: Value在编译时始终是已知的吗?
  2.   

是的,因为它是用常量表达式初始化的。但我将Value修改为constexpr而不仅仅是const

  
      
  1. 有没有办法检查constexpr函数/方法是否在编译时进行评估?
  2.   

是。尝试在constexpr表达式中使用它们。如果它有效,它们将在编译时进行评估。如果编译失败,那么它不会在编译时进行评估。

  
      
  1. 我理解定义为constexpr的成员/方法/函数不一定在编译期间进行评估,将Value定义为静态const的事实是否会改变这一点,或者我最好将此特定情况作为递归模板类实现?
  2.   

如果在常量表达式中使用成员,则强制在编译时对它们进行求值。所以,如果你关心,我只需要确保用常量表达式评估它们(通过constexpr)。