【问题标题】:std::ranges::sort is not usable as a 'constexpr' function when saving its return value in lambda functionstd::ranges::sort 在 lambda 函数中保存其返回值时不能用作“constexpr”函数
【发布时间】:2020-12-01 06:46:21
【问题描述】:

这个函数f可以将C++20范围算法对象作为参数然后使用它:

constexpr auto f(auto algo) {
  return [=] {
    algo(std::array{1, 0});
    return true;
  }();
}

它适用于std::ranges::sort

static_assert(f(std::ranges::sort));

但是当我将 algo 的返回值保存在 lambda 中时:

constexpr auto f(auto algo) {
  return [=] {
    auto it = algo(std::array{1, 0});
    return true;
  }();
}

GCC rejects and says:

<source>:10:16: error: non-constant condition for static assertion
   10 | static_assert(f(std::ranges::sort));
      |               ~^~~~~~~~~~~~~~~~~~~
<source>:10:16: error: 'constexpr auto f(auto:16) [with auto:16 = std::ranges::__sort_fn]' called in a constant expression
<source>:3:16: note: 'constexpr auto f(auto:16) [with auto:16 = std::ranges::__sort_fn]' is not usable as a 'constexpr' function because:
    3 | constexpr auto f(auto algo) {
      |                ^
<source>:7:4: error: call to non-'constexpr' function 'f<std::ranges::__sort_fn>::<lambda()>'
    4 |   return [=] {
      |          ~~~~~
    5 |     auto it = algo(std::array{1, 0});
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6 |     return true;
      |     ~~~~~~~~~~~~
    7 |   }();
      |   ~^~
<source>:4:10: note: 'f<std::ranges::__sort_fn>::<lambda()>' is not usable as a 'constexpr' function because:
    4 |   return [=] {
      |          ^

当我尝试保存algo 的返回值时,为什么这个函数变成非'constexpr'? 还是只是一个错误

更新:以下代码将是accepted by GCC,所以这很可能是一个错误,我已经提交了bug report.

constexpr auto f(auto algo, auto... args) {
  return [=] () mutable {
    auto it = algo(args...);
    return true;
  }();
}

// those are ok
static_assert(f(std::ranges::reverse, std::array{0})); 
static_assert(f(std::ranges::fill, std::array{0}, 0));
// those are not ok
// static_assert(f(std::ranges::sort, std::array{0}));    
// static_assert(f(std::ranges::replace, std::array{0}, 0, 0)); 
// static_assert(f(std::ranges::unique, std::array{0}));
// static_assert(f(std::ranges::next_permutation, std::array{0}));
// static_assert(f(std::ranges::prev_permutation, std::array{0}));

【问题讨论】:

    标签: c++ lambda constexpr c++20 std-ranges


    【解决方案1】:

    它适用于我,如果我将迭代器 it 声明为 constexpr:

    constexpr auto it = algo(std::array{1, 0});
    

    【讨论】:

    • 没错,但这并不能解释为什么。根据您的逻辑,this 也应该无法编译,因为a 不是constexpr
    • 对。我想可能是因为 int 是文字类型,而“它”的类型不是。但实际上std::array::iterator 是文字类型,std::ranges::sort 的定义是constexpr。但是,简单地对数组进行排序而不将其返回值分配给变量也可以编译。 godbolt.org/z/3a6oe5 所以我猜这是一个错误。
    • 不返回std::array::iterator
    • 我怀疑存在编译器错误或不允许函数为 constexpr 的复杂规则。此类问题通常需要深入解释或确认这是实施者的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    相关资源
    最近更新 更多