2016-04-01 19 views
8

Tôi muốn có chế độ xem được sắp xếp theo số std::vector<std::chrono::milliseconds> nhưng tôi không muốn sửa đổi vùng chứa ban đầu. std::reference_wrapper có vẻ hoàn hảo cho điều này và nó hoạt động tốt cho một vectơ số nguyên.Tại sao tôi không thể sắp xếp vectơ tham chiếu_wrapper <std :: chrono :: mili giây>?

tôi đã tạo ra ví dụ này nhỏ:

#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'; 
} 

nào sản xuất sản lượng dự kiến ​​(trừ sorted_durations mà không sắp xếp tất nhiên vì đó là nhận xét ra):

 
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 

Như bạn có thể thấy, vector gốc của các số nguyên numbers không thay đổi theo thao tác sắp xếp được thực hiện trên sorted_numbers - đó chính xác là điều tôi muốn cho vector sorted_durations. Nhưng khi tôi uncomment rằng dòng trình biên dịch của tôi được rất chéo với tôi và tôi phải thừa nhận rằng tôi không thể tìm ra những gì nó đang cố gắng để cho tôi biết. trình biên dịch của tôi là kêu vang ++ phiên bản 3.8 và tôi xây dựng chương trình ví dụ như vậy:

clang++ -std=c++11 test.cc

Và đây là đầu ra lỗi tôi nhận được:

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, 
    ^

Nó thực sự đi vào cho lâu hơn một chút, nhưng stackoverflow sẽ không hãy để tôi đăng tất cả 55000 ký tự của lỗi.

Bất cứ ai có thể vui lòng giải thích cho tôi những gì tôi đang làm sai hoặc tại sao điều này chỉ đơn giản là không thể (nếu đó là trường hợp)?

+4

Nó có vẻ như std :: reference_wrapper không cung cấp điều hành nhị phân < – Incomputable

+0

trên [trang tài liệu tham khảo] (http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper) không có toán tử nào để so sánh, vì vậy tôi nghĩ bạn cần phải viết cho riêng mình. – Incomputable

+1

Có bao nhiêu phần tử trong vectơ? Bạn không thể sao chép nó? Về cơ bản, bạn thực hiện điều đó với vectơ 'reference_wrapper'. –

Trả lời

14

Lỗi đầu tiên có vẻ khá rõ ràng:

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) 
      ~~~~^~~~~~~~~ 

Bạn không thể sử dụng < để so sánh hai reference_wrapper<duration<...>> đối tượng.

Chuyển đổi thành duration<...> không xảy ra vì (như nhận xét ở trên): operator< cho duration là mẫu chức năng và các đối số của nó không thể được suy ra từ reference_wrapper<duration<...>>.

Nếu bạn đã chuyển một phiên bản std::less<std::chrono::milliseconds> thành std::sort thì điều đó sẽ làm cho trình bao bọc được chuyển đổi thành loại thời lượng và được so sánh chính xác.

std::sort(sorted_durations.begin(), sorted_durations.end(), std::less<std::chrono::milliseconds>{}); 

này về cơ bản nói rằng bạn muốn sắp xếp các đối tượng bằng cách so sánh chúng như milliseconds không reference_wrapper<milliseconds>.

+0

Cảm ơn rất nhiều. Tôi đoán nhiều trang lỗi khiến tôi hoàn toàn bị mù với thông điệp rõ ràng ban đầu đó. Nó hoạt động hoàn hảo. –

+1

Luôn bắt đầu với lỗi đầu tiên :-) Với các mẫu C++, các lỗi sau này có thể là các tác dụng phụ của lỗi đầu tiên và có thể biến mất khi bạn giải quyết lỗi đầu tiên. –

4

mỗi @ đề nghị của Niall, bạn có thể sử dụng một lambda như so sánh cho 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(); }); 
+0

Phải. Nhưng trong trường hợp này 'std :: sort (sort_durations.begin(), sort_durations.end(), std :: less ());' sugested bởi @Jonathan Wakely đơn giản hơn. –

+1

Đồng ý, nó đơn giản hơn. –

Các vấn đề liên quan