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::reduce
的 libstdc++
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
我尝试使用 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::reduce
的 libstdc++
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