2016-04-01 8 views
8

std::vector<std::chrono::milliseconds>のソートされたビューが必要ですが、元のコンテナを変更したくありません。 std::reference_wrapperこれには完璧と思われ、整数ベクトルにはうまく機能します。あなたのようreference_wrapper <std :: chrono :: milliseconds>のベクトルをソートできないのはなぜですか?

 
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 

:(それはコメントアウトされているので、もちろん、ソートされていないことsorted_durations除く)期待される出力を生成し

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

私はこの小さな例を作成しました整数の元のベクトルnumbersは、sorted_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

をそれはSTDのように思える:: reference_wrapperは、[参照ページ]にバイナリ演算子< – Incomputable

+0

を提供していません(のhttp:/ /en.cppreference.com/w/cpp/utility/functional/reference_wrapper)比較のための演算子がないので、自分で記述する必要があると思います。 – Incomputable

+1

ベクトルにはいくつの要素がありますか?あなたはそれをコピーできませんか?基本的には 'reference_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) 
      ~~~~^~~~~~~~~ 

次の2つのreference_wrapper<duration<...>>オブジェクトを比較するために<を使用することはできません。 (コメントは上記の言うように)durationためoperator<が関数テンプレートであり、その引数がreference_wrapper<duration<...>>から推定することはできませんので

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

常に最初のエラーで始まります:-) C++のテンプレートでは、後のエラーのカスケードが最初のエラーの副作用である可能性があります。 –

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

しかし、この場合、@Jonathan Wakelyによると、std :: sort(sorted_durations.begin()、sorted_durations.end()、std :: less ()); –

+1

合意して、それはより簡単です。 –

関連する問題