有没有办法编译代码,或者我必须创建自己的lambda作为std::accumulate
的第四个参数?
#include <iostream>
#include <ranges>
#include <unordered_map>
#include <numeric>
namespace rv = std::ranges::views;
int main()
{
std::unordered_map<unsigned, unsigned> m = {{5, 3}};
auto values = m | rv::values;
std::cout << std::accumulate(values.begin(), values.end(), 0) << std::endl;
}
如果我理解正确的话,gcc
抛出的错误基本上是说begin
和end
产生不同的类型,而std::accumulate
不能推导出唯一的InputIterator
类型。完整的编译器输出为:
main.cpp:15:65: error: no matching function for call to 'accumulate(std::ranges::elements_view<std::ranges::ref_view<std::unordered_map<unsigned int, unsigned int> >, 1>::_Iterator<true>, std::__detail::_Node_iterator<std::pair<const unsigned int, unsigned int>, false, false>, int)'
15 | std::cout << std::accumulate(values.begin(), values.end(), 0) << std::endl;
| ^
In file included from /usr/local/include/c++/10.2.0/numeric:62,
from main.cpp:5:
/usr/local/include/c++/10.2.0/bits/stl_numeric.h:134:5: note: candidate: 'template<class _InputIterator, class _Tp> constexpr _Tp std::accumulate(_InputIterator, _InputIterator, _Tp)'
134 | accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
| ^~~~~~~~~~
/usr/local/include/c++/10.2.0/bits/stl_numeric.h:134:5: note: template argument deduction/substitution failed:
main.cpp:15:65: note: deduced conflicting types for parameter '_InputIterator' ('std::ranges::elements_view<std::ranges::ref_view<std::unordered_map<unsigned int, unsigned int> >, 1>::_Iterator<true>' and 'std::__detail::_Node_iterator<std::pair<const unsigned int, unsigned int>, false, false>')
15 | std::cout << std::accumulate(values.begin(), values.end(), 0) << std::endl;
| ^
In file included from /usr/local/include/c++/10.2.0/numeric:62,
from main.cpp:5:
/usr/local/include/c++/10.2.0/bits/stl_numeric.h:161:5: note: candidate: 'template<class _InputIterator, class _Tp, class _BinaryOperation> constexpr _Tp std::accumulate(_InputIterator, _InputIterator, _Tp, _BinaryOperation)'
161 | accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,
| ^~~~~~~~~~
/usr/local/include/c++/10.2.0/bits/stl_numeric.h:161:5: note: template argument deduction/substitution failed:
main.cpp:15:65: note: deduced conflicting types for parameter '_InputIterator' ('std::ranges::elements_view<std::ranges::ref_view<std::unordered_map<unsigned int, unsigned int> >, 1>::_Iterator<true>' and 'std::__detail::_Node_iterator<std::pair<const unsigned int, unsigned int>, false, false>')
15 | std::cout << std::accumulate(values.begin(), values.end(), 0) << std::endl;
| ^
gcc抛出的错误,如果我理解正确的话,基本上说
begin
和end
产生不同类型的
确实如此。在范围方面,elements_view
的iterator
和sentinel
是不同的类型。在C++20之前,这些类型必须是相同的,并且许多代码都是假设这一点编写的。不幸的是,我们还没有ranges::accumulate
可以为您妥善处理此问题。
在此之前,还有另一个测距适配器会强制一个测距的iterator
和sentinel
具有相同的类型(如果已经是这样的话,则为无操作(:views::common
:
auto values = m | rv::values | rv::common;
在这种情况下,它将创建common_iterator
s的视图,这基本上是一个variant<iterator, sentinel>
,它被封装为表现得像迭代器。