代码之家  ›  专栏  ›  技术社区  ›  ABu

std::使用视图累积std::ranges::views::values

  •  1
  • ABu  · 技术社区  · 4 年前

    是否有任何方法可以编译该代码,或者我必须创建自己的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::累加 无法推断唯一 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;
          |                                                                 ^
    
    
    1 回复  |  直到 4 年前
        1
  •  5
  •   Barry    4 年前

    如果我理解正确的话,gcc抛出的错误基本上是这样的 begin end 产生不同类型

    的确。在范围方面, elements_view s iterator sentinel 是不同类型的。在C++20之前,这些类型必须相同,并且许多代码都是在这样的假设下编写的。不幸的是,我们还没有 ranges::accumulate 这会为你妥善处理。

    在此之前,还有另一个范围适配器,它强制一个范围具有相同的类型 迭代器 哨兵 (或者如果已经是这样的话,就不要采取行动): views::common :

    auto values = m | rv::values | rv::common;
    

    在这种情况下,这将创建一个视图 common_iterator s、 这基本上是一个 variant<iterator, sentinel> 包装起来像迭代器一样。