我想要一个std::vector<std::chrono::milliseconds>
的排序视图,但我不想修改原始容器。 std::reference_wrapper
似乎是完美的,它可以很好地用于整数向量。
我创建了这个小例子:
#include <chrono>
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
int main()
{
std::vector<int> numbers{1, 42, 3, 9, 5};
std::vector<std::reference_wrapper<int>> sorted_numbers(numbers.begin(), numbers.end());
std::sort(sorted_numbers.begin(), sorted_numbers.end());
std::cout << "Numbers: ";
for (const auto& n : numbers)
std::cout << n << ' ';
std::cout << '\n';
std::cout << "Sorted numbers: ";
for (const auto& n : sorted_numbers)
std::cout << n << ' ';
std::cout << '\n';
std::cout << "Numbers: ";
for (const auto& n : numbers)
std::cout << n << ' ';
std::cout << '\n';
std::vector<std::chrono::milliseconds> durations{std::chrono::milliseconds{1},
std::chrono::milliseconds{42},
std::chrono::milliseconds{3},
std::chrono::milliseconds{9},
std::chrono::milliseconds{5}};
std::vector<std::reference_wrapper<std::chrono::milliseconds>>
sorted_durations(durations.begin(), durations.end());
// std::sort(sorted_durations.begin(), sorted_durations.end());
std::cout << "Durations: ";
for (const auto& d : durations)
std::cout << d.count() << ' ';
std::cout << '\n';
std::cout << "Sorted durations: ";
for (const auto& d : sorted_durations)
std::cout << d.get().count() << ' ';
std::cout << '\n';
std::cout << "Durations: ";
for (const auto& d : durations)
std::cout << d.count() << ' ';
std::cout << '\n';
}
哪个产生预期的输出(除了sorted_durations
当然没有排序,因为它被注释掉了):
Numbers: 1 42 3 9 5 Sorted numbers: 1 3 5 9 42 Numbers: 1 42 3 9 5 Durations: 1 42 3 9 5 Sorted durations: 1 42 3 9 5 Durations: 1 42 3 9 5
正如您所看到的,整数numbers
的原始向量在sorted_numbers
上完成的排序操作没有改变 - 这正是我对sorted_durations
向量的要求。但当我取消注释该行时,我的编译器与我交叉,我必须承认我无法弄清楚它试图告诉我什么。
我的编译器是clang ++版本3.8,我像这样构建示例程序:
clang++ -std=c++11 test.cc
这是我得到的错误输出:
In file included from test.cc:4:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/algorithm:62:
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_algo.h:1935:11: error: invalid operands to binary expression
('std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >' and 'std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >')
if (*__i < *__first)
~~~~ ^ ~~~~~~~~
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_algo.h:5308:12: note: in instantiation of function template specialization
'std::__heap_select<__gnu_cxx::__normal_iterator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > *,
std::vector<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >, std::allocator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > > > >
>' requested here
std::__heap_select(__first, __middle, __last);
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_algo.h:2310:24: note: in instantiation of function template specialization
'std::partial_sort<__gnu_cxx::__normal_iterator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > *,
std::vector<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >, std::allocator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > > > >
>' requested here
_GLIBCXX_STD_A::partial_sort(__first, __last, __last);
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_algo.h:5460:9: note: in instantiation of function template specialization
'std::__introsort_loop<__gnu_cxx::__normal_iterator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > *,
std::vector<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >, std::allocator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > > > >,
long>' requested here
std::__introsort_loop(__first, __last,
^
test.cc:35:10: note: in instantiation of function template specialization 'std::sort<__gnu_cxx::__normal_iterator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >
*, std::vector<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >, std::allocator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > > >
> >' requested here
std::sort(sorted_durations.begin(), sorted_durations.end());
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/chrono:488:7: note: candidate template ignored: could not match 'duration' against 'reference_wrapper'
operator<(const duration<_Rep1, _Period1>& __lhs,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/chrono:667:7: note: candidate template ignored: could not match 'time_point' against 'reference_wrapper'
operator<(const time_point<_Clock, _Dur1>& __lhs,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_pair.h:220:5: note: candidate template ignored: could not match 'pair' against 'reference_wrapper'
operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_iterator.h:297:5: note: candidate template ignored: could not match 'reverse_iterator' against
'reference_wrapper'
operator<(const reverse_iterator<_Iterator>& __x,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_iterator.h:347:5: note: candidate template ignored: could not match 'reverse_iterator' against
'reference_wrapper'
operator<(const reverse_iterator<_IteratorL>& __x,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_iterator.h:1055:5: note: candidate template ignored: could not match 'move_iterator' against 'reference_wrapper'
operator<(const move_iterator<_IteratorL>& __x,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_iterator.h:1061:5: note: candidate template ignored: could not match 'move_iterator' against 'reference_wrapper'
operator<(const move_iterator<_Iterator>& __x,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_vector.h:1421:5: note: candidate template ignored: could not match 'vector' against 'reference_wrapper'
operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/basic_string.h:2569:5: note: candidate template ignored: could not match 'basic_string' against 'reference_wrapper'
operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/basic_string.h:2581:5: note: candidate template ignored: could not match 'basic_string' against 'reference_wrapper'
operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/basic_string.h:2593:5: note: candidate template ignored: could not match 'const _CharT *' against
'std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >'
operator<(const _CharT* __lhs,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/array:238:5: note: candidate template ignored: could not match 'array' against 'reference_wrapper'
operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/tuple:824:5: note: candidate template ignored: could not match 'tuple' against 'reference_wrapper'
operator<(const tuple<_TElements...>& __t,
^
In file included from test.cc:4:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/algorithm:62:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_algo.h:61:
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_heap.h:235:35: error: invalid operands to binary expression ('std::reference_wrapper<std::chrono::duration<long,
std::ratio<1, 1000> > >' and 'std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >')
if (*(__first + __secondChild) < *(__first + (__secondChild - 1)))
~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_heap.h:407:9: note: in instantiation of function template specialization
'std::__adjust_heap<__gnu_cxx::__normal_iterator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > *,
std::vector<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >, std::allocator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > > > >,
long, std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > >' requested here
std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value));
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_algo.h:1933:12: note: in instantiation of function template specialization
'std::make_heap<__gnu_cxx::__normal_iterator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > *,
std::vector<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >, std::allocator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > > > >
>' requested here
std::make_heap(__first, __middle);
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_algo.h:5308:12: note: in instantiation of function template specialization
'std::__heap_select<__gnu_cxx::__normal_iterator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > *,
std::vector<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >, std::allocator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > > > >
>' requested here
std::__heap_select(__first, __middle, __last);
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_algo.h:2310:24: note: in instantiation of function template specialization
'std::partial_sort<__gnu_cxx::__normal_iterator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > *,
std::vector<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >, std::allocator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > > > >
>' requested here
_GLIBCXX_STD_A::partial_sort(__first, __last, __last);
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_algo.h:5460:9: note: in instantiation of function template specialization
'std::__introsort_loop<__gnu_cxx::__normal_iterator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > *,
std::vector<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >, std::allocator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > > > >,
long>' requested here
std::__introsort_loop(__first, __last,
^
test.cc:35:10: note: in instantiation of function template specialization 'std::sort<__gnu_cxx::__normal_iterator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >
*, std::vector<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >, std::allocator<std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > > > >
> >' requested here
std::sort(sorted_durations.begin(), sorted_durations.end());
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/chrono:488:7: note: candidate template ignored: could not match 'duration' against 'reference_wrapper'
operator<(const duration<_Rep1, _Period1>& __lhs,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/chrono:667:7: note: candidate template ignored: could not match 'time_point' against 'reference_wrapper'
operator<(const time_point<_Clock, _Dur1>& __lhs,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_pair.h:220:5: note: candidate template ignored: could not match 'pair' against 'reference_wrapper'
operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_iterator.h:297:5: note: candidate template ignored: could not match 'reverse_iterator' against
'reference_wrapper'
operator<(const reverse_iterator<_Iterator>& __x,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_iterator.h:347:5: note: candidate template ignored: could not match 'reverse_iterator' against
'reference_wrapper'
operator<(const reverse_iterator<_IteratorL>& __x,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_iterator.h:1055:5: note: candidate template ignored: could not match 'move_iterator' against 'reference_wrapper'
operator<(const move_iterator<_IteratorL>& __x,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_iterator.h:1061:5: note: candidate template ignored: could not match 'move_iterator' against 'reference_wrapper'
operator<(const move_iterator<_Iterator>& __x,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_vector.h:1421:5: note: candidate template ignored: could not match 'vector' against 'reference_wrapper'
operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/basic_string.h:2569:5: note: candidate template ignored: could not match 'basic_string' against 'reference_wrapper'
operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/basic_string.h:2581:5: note: candidate template ignored: could not match 'basic_string' against 'reference_wrapper'
operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/basic_string.h:2593:5: note: candidate template ignored: could not match 'const _CharT *' against
'std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >'
operator<(const _CharT* __lhs,
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/array:238:5: note: candidate template ignored: could not match 'array' against 'reference_wrapper'
operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
^
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/tuple:824:5: note: candidate template ignored: could not match 'tuple' against 'reference_wrapper'
operator<(const tuple<_TElements...>& __t,
^
它实际上持续了一段时间,但stackoverflow不会让我发布错误的所有55000个字符。
任何人都可以向我解释我做错了什么或为什么这根本不可能(如果是这样的话)?
答案 0 :(得分:15)
第一个错误似乎很清楚:
In file included from [...]/algorithm:62:
[...]/bits/stl_algo.h:1935:11: error: invalid operands to binary expression
('std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >' and 'std::reference_wrapper<std::chrono::duration<long, std::ratio<1, 1000> > >')
if (*__i < *__first)
~~~~ ^ ~~~~~~~~
您无法使用<
来比较两个reference_wrapper<duration<...>>
个对象。
转换为duration<...>
不会发生,因为(如上面的评论所述)operator<
duration
是一个函数模板,其参数不能从{{1}推导出来}。
如果您将reference_wrapper<duration<...>>
的实例传递给std::less<std::chrono::milliseconds>
,那么这会导致包装器转换为持续时间类型,并进行正确比较。
std::sort
这基本上表示您希望通过将对象比较为 std::sort(sorted_durations.begin(), sorted_durations.end(), std::less<std::chrono::milliseconds>{});
而不是milliseconds
来对对象进行排序。
答案 1 :(得分:4)
Per @ Niall的建议,您可以使用lambda
作为sort()
的比较器:
std::sort(sorted_durations.begin(), sorted_durations.end(),
[](const std::reference_wrapper<std::chrono::milliseconds> &a,
const std::reference_wrapper<std::chrono::milliseconds> &b)
-> bool { return a.get() < b.get(); } );