【问题标题】:Static member function not accepted as constexpr parameter静态成员函数不被接受为 constexpr 参数
【发布时间】:2014-03-16 20:14:21
【问题描述】:

以下代码被clang接受,被gcc拒绝。我想知道这是一个错误还是我遗漏了什么:

#include <array>

template<typename T>
static constexpr T Apply(T in, T fun(T)) {
  return fun(in);
}

template <typename T, size_t N> struct Triangle {
  using Ar = std::array<T, N>;
  static constexpr Ar foo(Ar line) { return line; }
  static constexpr Ar results = Apply<Ar>( {{ 1 }}, foo ); // foo({1}); is ok 
};
template <typename T, size_t N> constexpr std::array<T, N> Triangle<T, N>::results;

int main() {
  Triangle<unsigned long, 10>::results[0];
}

GCC 错误信息是:

binom2.cpp: In instantiation of ‘constexpr const std::array<long unsigned int, 10ul> Triangle<long unsigned int, 10ul>::results’:
binom2.cpp:16:32:   required from here
binom2.cpp:11:57:   in constexpr expansion of ‘Apply<std::array<long unsigned int, 10ul> >(std::array<long unsigned int, 10ul>{std::__array_traits<long unsigned int, 10ul>::_Type{1ul}}, Triangle<T, N>::foo<long unsigned int, 10ul>)’
binom2.cpp:5:16: error: expression ‘Triangle<T, N>::foo<long unsigned int, 10ul>’ does not designate a constexpr function
   return fun(in);
                ^

【问题讨论】:

  • 我认为clang在这里是正确的,因为函数调用替换的规则。
  • 我想是的,如果我们将 Ar 类型更改为 intApply&lt;Ar&gt;(1, foo) 将按预期工作。
  • @Jarod42 :是的,我在尝试减少问题时注意到了这一点。对不起,我忘了提。
  • 借助 Apply&lt;Ar&gt; 的专业化(与 Apply&lt;T&gt; 做同样的事情),它可以工作...... gcc 的 SO 错误(我的部分是 4.8.1)。
  • @Jarod42:对不起!我不明白你的意思。你能写(可能在一个答案中,我会接受它)有效的变化,这是一个错误的证据吗?

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


【解决方案1】:

我已将 gcc (4.8.1) 错误减少到以下内容:

#include <array>

using Ar = std::array<unsigned long, 10>;

template<typename T>
constexpr T Apply(const T& in, T (*f)(const T&)) { return f(in); }

#if 1 // if disable, bug occurs
      // error: expression 'id' does not designate a constexpr function
template<>
constexpr Ar Apply<Ar>(const Ar& in, Ar (*f)(const Ar&)) { return f(in); }
#endif

constexpr Ar ApplyAr(const Ar& in, Ar (*f)(const Ar&)) { return f(in); }

static constexpr Ar id(const Ar& line) { return line; }
static constexpr Ar ar1 = {{1}};
static constexpr Ar results1 = Apply<Ar>(ar1, &id); // Fail when #if 0
static constexpr Ar results2 = ApplyAr(ar1, &id);
static constexpr Ar results3 = id(ar1);

int main() {
    return 0;
}

【讨论】:

  • 谢谢!我会向 GCC 报告。
【解决方案2】:

这绝对是一个错误。这是我设法提供的最精简的版本:

constexpr int Apply(int f(const int)) { return f(0); }
using Ar = int;
constexpr int id(const Ar i) { return i; }
constexpr int results1 = Apply(id);

id 的定义中将Ar 更改为int 会使问题消失。所以这显然是一个错误!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-05
    • 2012-07-16
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 2014-04-06
    • 1970-01-01
    相关资源
    最近更新 更多