【问题标题】:string literal parameter not accepted to a constexpr functionconstexpr 函数不接受字符串文字参数
【发布时间】:2013-05-05 17:41:49
【问题描述】:

在 g++ 4.9.0 (20130421) 上调用下面的 extract 函数对我不起作用。我得到的错误是 s1 不是常量表达式。如果 i 可以初始化为 constexpr,那么 jk 也应该初始化。那是错的吗?

#include <tuple>

template <unsigned N1, unsigned N2> 
constexpr bool strmatch(const char (&s1)[N1], const char (&s2)[N2], unsigned i = 0)
{
  return (s1[i]==s2[i]) ? 
            (s1[i]=='\0') ? 
               true
               : strmatch(s1, s2, i+1) 
            : false;
}

template<unsigned N>
constexpr int extract(const std::tuple<int, int> & t1, const char (&array)[N]) {
  return std::get<strmatch(array, "m0")>(t1);
}

int main(void)
{
  constexpr int i = strmatch("m0", "m0");  // OK
  constexpr int j = extract(std::make_tuple(10, 20), "m0"); 
  constexpr int k = extract(std::make_tuple(10, 20), "m1");

  return 0;
}

【问题讨论】:

  • 我有 75% 的把握这是编译器错误。函数调用替换应该可以解决任何引用绑定问题。

标签: gcc c++11 g++ constexpr


【解决方案1】:

您的代码格式不正确。问题是array不是核心常量表达式,所以不能在std::get调用中的模板参数中使用:

template<unsigned N>
constexpr int extract(const std::tuple<int, int> & t1, const char (&array)[N]) {
  return std::get<strmatch(array, "m0")>(t1);
}

请记住,constexpr 函数可以在运行时调用:此代码将在转换期间(在评估对 strmatch 的调用时)使用此函数 (array) 的运行时参数值。

【讨论】:

  • 这太蹩脚了!我可以将 strmatch 的结果分配给一个 constexpr 整数 (i) 并将其用作 std::get 的模板参数。我应该能够做到这一点而不必使用命名变量。这不就是函数调用替换背后的想法吗?
  • 函数调用替换只是描述如何评估函数调用的一种形式。重申一下,您的函数 extract&lt;3&gt; 可以在运行时调用,如果允许的话,这通常需要在运行时进行模板实例化。
  • 对。但是只要 extract 的所有调用(在翻译单元中)都可以在编译时进行评估,那么代码应该可以工作,对吧?
  • 不,该函数必须在运行时仍然有效,即使您从未碰巧那样调用它。 constexpr 不像模板实例化——它不允许你生成代码(如果你可以在模板参数中使用 constexpr 函数的参数,这是必要的)。
猜你喜欢
  • 1970-01-01
  • 2017-08-11
  • 1970-01-01
  • 1970-01-01
  • 2017-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多