有没有一种方法可以在没有 lambda 的情况下投影到压缩向量元组

问题描述 投票:0回答:1

如下面的代码所示,我可以使用

std::ranges::sort
对压缩向量进行排序,使用 lambda 指定应由第一个向量完成排序。有没有一种方法可以使用投影,指定元组字段名称(或其他名称),如示例(2)和(3)所示?

示例 (2) 在 range3 中工作,其中元素被实现为

std::pair
(或者至少可以通过这种方式访问它)。现在有了标准库范围,它是用元组实现的,这种方法不起作用。

我可以在没有 lambda 的情况下完成这个任务吗?

我为什么关心?我需要保留单独且可用的比较器和投影,以便与我的调整版本一起使用。额外的好处是代码更少,更容易编写、阅读和支持。

#include <algorithm>
#include <ranges>
#include <vector>

int main()
{
    std::vector<float> x_values = { 3.0f, 1.0f, 2.0f };
    std::vector<float> y_values = { 5.0f, 6.0f, 7.0f };

    // (1) Compiles
    std::ranges::sort(std::ranges::views::zip(x_values, y_values), [](const auto& lhs, const auto& rhs) {
        return std::get<0>(lhs) < std::get<0>(rhs);
    });

    // (2) Doesn't compile since in ranges they use tuples
    std::ranges::sort(std::ranges::views::zip(x_values, y_values), std::less<>{}, &std::pair<int, int>::first);

    // (3) I guess doesn't compile since get is a member function template, not a member field
    std::ranges::sort(std::ranges::views::zip(x_values, y_values), std::less<>{}, &std::get<0>);
}

这是演示

尝试 (2) 给出错误消息:

In file included from <source>:2:
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/ranges:4558:14: error: type constraint differs in template redeclaration
 4558 |     template<copy_constructible _Fp, input_range... _Ws>
      |              ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/ranges:4458:14: note: in instantiation of template class 'std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>::_Iterator<true>' requested here
 4458 |     { return _Iterator<true>(__detail::__tuple_transform(ranges::begin, _M_views)); }
      |              ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:979:23: note: in instantiation of member function 'std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>::begin' requested here
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |                              ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:979:6: note: in instantiation of requirement here
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:977:32: note: while substituting template arguments into constraint expression here
  977 |       concept __member_begin = requires(_Tp& __t)
      |                                ^~~~~~~~~~~~~~~~~~
  978 |         {
      |         ~
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  980 |         };
      |         ~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:112:50: note: while checking the satisfaction of concept '__member_begin<std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>> &>' requested here
  112 |         requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
      |                                                         ^~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:112:50: note: (skipping 4 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:501:21: note: while substituting template arguments into constraint expression here
  501 |     concept range = requires(_Tp& __t)
      |                     ^~~~~~~~~~~~~~~~~~
  502 |       {
      |       ~
  503 |         ranges::begin(__t);
      |         ~~~~~~~~~~~~~~~~~~~
  504 |         ranges::end(__t);
      |         ~~~~~~~~~~~~~~~~~
  505 |       };
      |       ~
...
      |                              ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:635:33: note: because '*__i' would be invalid: indirection requires pointer operand ('std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>' invalid)
  635 |       = requires(_Iter __i) { { *__i } -> __detail::__can_reference; }
      |                                 ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_algo.h:1794:7: note: candidate template ignored: constraints not satisfied [with _Range = zip_view<all_t<vector<float, allocator<float>> &>, all_t<vector<float, allocator<float>> &>>, _Comp = std::less<>, _Proj = int std::pair<int, int>::*]
 1794 |       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
      |       ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_algo.h:1792:16: note: because 'sortable<iterator_t<zip_view<ref_view<vector<float, allocator<float> > >, ref_view<vector<float, allocator<float> > > > >, std::less<void>, int std::pair<int, int>::*>' evaluated to false
 1792 |       requires sortable<iterator_t<_Range>, _Comp, _Proj>
      |                ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:950:43: note: because substituted constraint expression is ill-formed: constraints not satisfied for alias template 'projected' [with _Iter = std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>::_Iterator<true>, _Proj = int std::pair<int, int>::*]
  950 |       && indirect_strict_weak_order<_Rel, projected<_Iter, _Proj>>;
      |                                           ^
3 errors generated.
Compiler returned: 1

尝试 (3) 给出错误消息:

In file included from <source>:2:
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/ranges:4558:14: error: type constraint differs in template redeclaration
 4558 |     template<copy_constructible _Fp, input_range... _Ws>
      |              ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/ranges:4458:14: note: in instantiation of template class 'std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>::_Iterator<true>' requested here
 4458 |     { return _Iterator<true>(__detail::__tuple_transform(ranges::begin, _M_views)); }
      |              ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:979:23: note: in instantiation of member function 'std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>::begin' requested here
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |                              ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:979:6: note: in instantiation of requirement here
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:977:32: note: while substituting template arguments into constraint expression here
  977 |       concept __member_begin = requires(_Tp& __t)
      |                                ^~~~~~~~~~~~~~~~~~
  978 |         {
      |         ~
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  980 |         };
      |         ~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:112:50: note: while checking the satisfaction of concept '__member_begin<std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>> &>' requested here
  112 |         requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
      |                                                         ^~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:112:50: note: (skipping 4 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:501:21: note: while substituting template arguments into constraint expression here
  501 |     concept range = requires(_Tp& __t)
      |                     ^~~~~~~~~~~~~~~~~~
  502 |       {
      |       ~
  503 |         ranges::begin(__t);
      |         ~~~~~~~~~~~~~~~~~~~
  504 |         ranges::end(__t);
      |         ~~~~~~~~~~~~~~~~~
  505 |       };
      |       ~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:1059:12: note: while checking the satisfaction of concept 'range<std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>>' requested here
 1059 |   template<range _Range>
      |            ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:1059:12: note: while substituting template arguments into constraint expression here
 1059 |   template<range _Range>
      |            ^~~~~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_algo.h:1793:17: note: while checking constraint satisfaction for template 'borrowed_iterator_t<std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>>' required here
 1793 |       constexpr borrowed_iterator_t<_Range>
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:11:19: note: while substituting deduced template arguments into function template 'operator()' [with _Range = zip_view<all_t<vector<float, allocator<float>> &>, all_t<vector<float, allocator<float>> &>>, _Comp = (lambda at <source>:11:65), _Proj = (no value)]
   11 |         std::ranges::sort(std::ranges::views::zip(x_values, y_values), [](const auto& lhs, const auto& rhs) {
      |                          ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/ranges:4829:12: note: previous template declaration is here
 4829 |   template<copy_constructible _Fp, input_range... _Vs>
      |            ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/ranges:4558:14: error: type constraint differs in template redeclaration
 4558 |     template<copy_constructible _Fp, input_range... _Ws>
      |              ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/ranges:4458:30: note: in instantiation of template class 'std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>::_Iterator<false>' requested here
 4458 |     { return _Iterator<true>(__detail::__tuple_transform(ranges::begin, _M_views)); }
      |                              ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:979:23: note: in instantiation of member function 'std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>::begin' requested here
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |                              ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:979:6: note: in instantiation of requirement here
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:977:32: note: while substituting template arguments into constraint expression here
  977 |       concept __member_begin = requires(_Tp& __t)
      |                                ^~~~~~~~~~~~~~~~~~
  978 |         {
      |         ~
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  980 |         };
      |         ~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:112:50: note: while checking the satisfaction of concept '__member_begin<std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>> &>' requested here
  112 |         requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
      |                                                         ^~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:112:50: note: (skipping 4 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:501:21: note: while substituting template arguments into constraint expression here
  501 |     concept range = requires(_Tp& __t)
      |                     ^~~~~~~~~~~~~~~~~~
  502 |       {
      |       ~
  503 |         ranges::begin(__t);
      |         ~~~~~~~~~~~~~~~~~~~
  504 |         ranges::end(__t);
      |         ~~~~~~~~~~~~~~~~~
  505 |       };
      |       ~
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_base.h:1059:12: note: while checking the satisfaction of concept 'range<std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>>' requested here
 1059 |   template<range _Range>
      |            ^
...
  635 |       = requires(_Iter __i) { { *__i } -> __detail::__can_reference; }
      |                                 ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_algo.h:1794:7: note: candidate template ignored: constraints not satisfied [with _Range = zip_view<all_t<vector<float, allocator<float>> &>, all_t<vector<float, allocator<float>> &>>, _Comp = std::less<>, _Proj = __enable_if_t<(0UL >= sizeof...(_Elements))> (*)(const tuple<> &)]
 1794 |       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
      |       ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/ranges_algo.h:1792:16: note: because 'sortable<iterator_t<zip_view<ref_view<vector<float, allocator<float> > >, ref_view<vector<float, allocator<float> > > > >, std::less<void>, void (*)(const std::tuple<> &)>' evaluated to false
 1792 |       requires sortable<iterator_t<_Range>, _Comp, _Proj>
      |                ^
/opt/compiler-explorer/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/bits/iterator_concepts.h:950:43: note: because substituted constraint expression is ill-formed: constraints not satisfied for alias template 'projected' [with _Iter = std::ranges::zip_view<std::ranges::ref_view<std::vector<float>>, std::ranges::ref_view<std::vector<float>>>::_Iterator<true>, _Proj = void (*)(const std::tuple<> &)]
  950 |       && indirect_strict_weak_order<_Rel, projected<_Iter, _Proj>>;
      |                                           ^
5 errors generated.
Compiler returned: 1

(如果您知道如何在这里折叠或缩小错误日志的字段,请告诉我或更新问题;我看到它们太大,但看不到调整的方法)。

c++ tuples range std
1个回答
0
投票

我需要保留单独且可用的比较器和投影,以便与我的调整版本一起使用。额外的好处是代码更少,更容易编写、阅读和支持。

我对老式函子的看法,可自定义如下:

template<std::size_t N>
struct Get {
    template<typename T>
    constexpr auto operator()(const T& tuple) const {
        return std::get<N>(tuple);
    }
};

现在你可以写:

auto zipped = std::views::zip(x_values, y_values, z_values);

// Sort by first element (x_values)
std::ranges::sort(zipped, std::less{}, Get<0>{});

// Or ...sort by second element (y_values)
std::ranges::sort(zipped, std::less{}, Get<1>{});

// so on...
````
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.