9

我有一个看起来像这样的 constexpr 函数:

constexpr int foo(int bar)
{
   static_assert(bar>arbitrary_number, "Use a lower number please");

   return something_const;
}

但是,用 GCC 4.6.3 编译它一直告诉我

错误:“bar”不能出现在常量表达式中

我尝试了类似的东西

constexpr int foo(constexpr const int bar)
{
   static_assert(bar>arbitrary_number, "Use a lower number please");

   return something_const;
}

但 constexpr 不能用于函数参数。

是否有一些简单的方法可以告诉编译器 bar 始终是编译时间常数?

4

3 回答 3

17

是否有一些简单的方法可以告诉编译器 bar 始终是编译时间常数?

如果bar始终是编译时常量,那么您应该将函数编写为:

template<int bar>
constexpr int foo()
{
   static_assert(bar>arbitrary_number, "Use a lower number please");
   return something_const;
}

因为如果您不这样做,而是编写您已经编写的内容,那么在这种情况下,也可以使用非常量参数调用该函数;只是当您传递非常量参数时,该函数将失去它的constexpr -ness。

请注意,上面的代码arbitrary_number也应该是常量表达式,否则将无法编译。

于 2012-03-20T15:43:06.503 回答
5

constexpr函数可以在编译时进行评估,一般标准不会强制执行(您可以通过在常量表达式中使用函数来强制在编译时评估函数,例如初始化constexpr变量)。

此外,一个论据constexpr函数的参数实际上不是恒定的,它们可能会随着每次调用而改变(即使在编译时进行评估)。

一种解决方法是使用非类型模板来传递bar,如果它始终是编译时间常数(它似乎是)。

于 2012-03-20T15:44:45.500 回答
0

foo可以通过以下方式使用:

int i;
std::cin >> i;
foo("foo", i);

如您所见i,它并不完全是上面的常量表达式,但它仍然可以与constexpr函数一起使用。constexpr函数(和函数模板)是一种奇怪的野兽,它保证 egfoo(p, i)是一个常量表达式 iffp并且i也是,仍然可以像常规函数一样使用。

如果你的函数的参数真正意味着始终是常量表达式,那么它们应该是模板参数,而不是函数参数。

于 2012-03-20T15:44:29.337 回答