2

任何 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 函数进行一些运行时评估?

4

3 回答 3

0

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

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

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

如果您想专门用于编译时计算的函数,请使用不同的函数来清楚地说明您的意图。

于 2013-03-05T23:23:59.387 回答
0

在函数中,不可能检查参数以查看完整的调用表达式是否为常量表达式。但是您可以在调用站点实现一个宏来测试相同的东西,根据表达式是否为常量表达式来评估true_type或在编译时进行评估false_type

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

详细信息在this answer to another question。(我自己的回答,为交叉发帖道歉!)

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

于 2016-11-04T07:42:32.613 回答
-3

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

#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函数模板并不总是可用于常量表达式。所以这导致了一个像这样的解决方案,这个有点人为的例子:

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) ;
} 
于 2013-03-06T03:44:20.233 回答