【问题标题】:How to tell static_assert that constexpr function arguments are const?如何告诉 static_assert constexpr 函数参数是 const?
【发布时间】:2012-03-20 15:37:22
【问题描述】:

我有一个看起来像这样的 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 始终是编译时常量?

【问题讨论】:

标签: c++ c++11 constexpr


【解决方案1】:

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

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

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

因为如果你不这样做,而是写你已经写的东西,那么在这种情况下,函数可以non-const调用论据;只是当你传递非常量参数时,函数将失去它的 constexpr-ness。

注意上面代码中arbitrary_number也应该是常量表达式,否则编译不出来。

【讨论】:

  • template&lt;int bar&gt; 是什么类型的语法?完整的模板专业化,如 template &lt;&gt; ...?
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-27
      • 1970-01-01
      • 1970-01-01
      • 2016-09-16
      • 1970-01-01
      • 2019-08-25
      • 1970-01-01
      相关资源
      最近更新 更多