找出参数是constexpr

时间:2013-03-05 23:04:10

标签: c++

任何type_traits或方法都可以找出这些参数是否为constexpr?

实施例

size_t fibo_runtime(size_t num)
{
  //implementation
}

constexpr size_t fibo(size_t num)
{
    return is_constexpr<size_t>::value ? //this type traits looks weird and unreasonable
           (num > 1 ? fibo(num - 1) * num : 1) :
           fibo_runtime(num);
}

constexpr可以应用于constexpr参数和 参数在运行时确定。然而, 在运行时,递归可能效率不高。

我们还是要分开执行 constexpr函数的运行时和编译时间? 如果我们不能这样做,我们是否可以强制执行用户 无法使用constexpr函数来执行某些运行时 评价

3 个答案:

答案 0 :(得分:0)

常量表达式(constexpr)的本质是常量。所以运行时评估与否,它们不会改变它们的任何行为,评估永远不会在运行时完成。

如果在运行时使用constexpr函数(不是简单地通过直接调用它),那么它将被称为普通函数,因为在运行时,表达式无法自然地解析为常量。 / p>

如果你想根据编译时或运行时实现一些不同的实现,它会(如果你实现它)对开发人员来说真的很不安,因为根据你调用它的方式,函数不会有相同的行为!因此很明显,这种行为不会/不会/不应该实施。

如果您想专门编写一个函数进行编译时计算,请使用不同的函数来清楚地表明您的意图。

答案 1 :(得分:0)

在函数中,不可能检查参数以查看完整的调用表达式是否为常量表达式。但是你可以在调用站点实现一个宏来测试同样的东西,在编译时评估为true_typefalse_type,具体取决于表达式是否为常量表达式

IS_A_CONSTANT_EXPRESSION(  fibo(5)          )    // is constant
IS_A_CONSTANT_EXPRESSION(  fibo(time(NULL)  )    // is not constant

详情见this answer另一个问题。 (我自己的回答,为交叉发帖道歉!)

然后你可以实现另一个宏FIBO( expr )来很好地包装它,并根据需要调用正确的版本。

答案 2 :(得分:-2)

我认为这可能会让你得到你想要的东西

#include <iostream>

template <typename T>
class is_constexpr
{
   typedef char true_type ;
   struct false_type { true_type _[2] ; } ;

   template <typename U>
   static true_type has_constexpr( U & ) ;

   template <typename U>
   static false_type has_constexpr(...) ;

   public:
      enum { value = ( sizeof(has_constexpr<T>(0)) == sizeof(true_type)) } ;
} ;

int main()
{
   constexpr int i = 10 ;
   int k = 20 ;

   std::cout << is_constexpr<decltype(i)>::value << std::endl ;
   std::cout << is_constexpr<decltype(k)>::value << std::endl ;   
}

我使用Understanding SFINAE作为参考。

进行更多研究我认为我对问题的其他部分的答案是肯定的,因为它看起来是constexpr函数模板is not always usable in a constant expression。所以这导致了一个像这样的解决方案,这个有点人为的例子:

template <typename T>
T f2( T num )
{ 
   return num + 1;
}

template <typename T>
constexpr T f1( T num )
{
   return num ;
}

template <typename T>
constexpr T f(T num)
{
   return  is_constexpr<T>::value ? f1(num) : f2(num) ;
}