std::reduce 与函子

std::reduce with functor

我尝试使用 std::reduce 和仿函数来计算数组中的字符数。 GCC 在 MSVC 中编译和工作时出错。 link here

#include <iostream>
#include <array>
#include <numeric>
#include <cstring>

int main()
{
    std::array arr{ "Mickey","Minnie","Jerry" };
    struct StringLength
    {
        auto operator()(const char* l, size_t r)
        {
            return strlen(l) + r;
        }
        auto operator()(size_t l, const char* r)
        {
            return l + strlen(r);
        }
        auto operator()(const char* l, const char* r)
        {
            return strlen(l) + strlen(r);
        }
        auto operator()(size_t l, size_t r)
        {
            return l + r;
        }
    };
    std::cout << std::reduce(arr.begin(), arr.end(), size_t{}, StringLength());
    // this ^ works in MSVC
}

GCC 10.1 错误,因为重要信息应该 隐藏在 link:

后面
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/numeric:
In instantiation of '_Tp std::reduce(_InputIterator, _InputIterator, _Tp, _BinaryOperation)
[with _InputIterator = const char**; _Tp = long unsigned int;
 _BinaryOperation = main()::StringLength]':

<source>:29:78:   required from here

/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/numeric:263:21: error:
static assertion failed

  263 |       static_assert(is_convertible_v<value_type, _Tp>);
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我同意 dewaffled 这是一个错误。 std::reducelibstdc++ implementation 看起来像这样:

template<typename InputIt, typename Tp, typename BinOp>
Tp reduce(InputIt first, InputIt last, Tp init, BinOp binary_op) {
    using value_type = typename iterator_traits<InputIt>::value_type;
    static_assert(is_invocable_r_v<Tp, BinOp&, Tp&, Tp&>);
    static_assert(is_convertible_v<value_type, Tp>);
    // ...
}

我无法在 the standard that iterator's value_type has to be convertible into Tp. Moreover, this requirement is not necessary at all. If you remove that static assert, your code will compile 中找到应有的要求。

来自 GCC Bugzilla 的更新

Fixed for 9.5, 10.4 and 11.2.
Jonathan Wakely, 2021-06-18