2016-04-01 9 views
8

मुझे std::vector<std::chrono::milliseconds> का एक क्रमबद्ध दृश्य चाहिए, लेकिन मैं मूल कंटेनर को संशोधित नहीं करना चाहता हूं। std::reference_wrapper इसके लिए बिल्कुल सही लगता है और यह पूर्णांक के वेक्टर के लिए ठीक काम करता है।मैं संदर्भ_wrapper <std :: chrono :: milliseconds> के वेक्टर को सॉर्ट क्यों नहीं कर सकता?

#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 

आप के रूप में देख सकते हैं, पूर्णांक के मूल वेक्टर numberssorted_numbers पर किए गए सॉर्ट ऑपरेशन द्वारा अपरिवर्तित है - यह वही है जो मैं sorted_durations वेक्टर के लिए भी चाहता हूं। लेकिन जब मैं उस रेखा को अनजान करता हूं तो मेरा कंपाइलर मेरे साथ बहुत पार हो जाता है और मुझे यह स्वीकार करना होगा कि मैं यह नहीं समझ सकता कि यह मुझे क्या बताने की कोशिश कर रहा है। मेरे संकलक बजना ++ संस्करण 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 वर्ण पोस्ट करने दें।

क्या कोई मुझे बता सकता है कि मैं क्या गलत कर रहा हूं या यह क्यों संभव नहीं है (यदि ऐसा है)?

+4

यह एसटीडी की तरह लगता है :: reference_wrapper [संदर्भ पेज] पर द्विआधारी ऑपरेटर < – Incomputable

+0

प्रदान नहीं करता है (http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper) तुलना के लिए कोई ऑपरेटर नहीं है, इसलिए मुझे लगता है कि आपको अपना खुद लिखना होगा। – Incomputable

+1

वेक्टर में कितने तत्व हैं? क्या आप इसे कॉपी नहीं कर सकते? आप मूल रूप से 'context_wrapper' वेक्टर के साथ वैसे भी करते हैं। –

उत्तर

14

पहले त्रुटि बहुत स्पष्ट लगता है:

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<...> करने के लिए रूपांतरण नहीं होता है क्योंकि (जैसा कि एक टिप्पणी के ऊपर का कहना है) duration के लिए operator< एक समारोह टेम्पलेट है और अपने तर्कों reference_wrapper<duration<...>> से निष्कर्ष निकाला नहीं जा सकता है।

आप std::less<std::chrono::milliseconds>std::sort करने का एक उदाहरण से पारित कर दिया है तो उस का कारण होगा रैपर अवधि प्रकार के लिए परिवर्तित किया, और सही ढंग से की तुलना में।

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

यह मूलतः आप उन्हें milliseconds नहीं reference_wrapper<milliseconds> के रूप में की तुलना द्वारा वस्तुओं क्रमबद्ध करना चाहते हैं कहते हैं।

+0

बहुत बहुत धन्यवाद। मुझे लगता है कि त्रुटियों के कई पृष्ठों ने मुझे प्रारंभिक स्पष्ट संदेश में पूरी तरह से अंधा कर दिया है। यह पूरी तरह से काम करता है। –

+1

हमेशा पहली त्रुटि से शुरू करें :-) सी ++ टेम्पलेट्स के साथ बाद की त्रुटियों का कैस्केड उस पहले के दुष्प्रभाव हो सकता है, और जब आप पहले को हल करते हैं तो शायद दूर जा सकते हैं। –

4

प्रति @ नियाल के सुझाव, आप के लिए sort() तुलनित्र के रूप में एक lambda उपयोग कर सकते हैं:

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

दाएं। लेकिन इस मामले में 'std :: sort (sorted_durations.begin(), sorted_durations.end(), std :: less ()); 'जोनाथन वाकीली द्वारा परेशान के रूप में सरल है। –

+1

सहमत, यह आसान है। –

संबंधित मुद्दे