9

の並べ替えられたビューが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コメントアウトされているため、もちろんソートされていません):

数字: 1 42 3 9 5
並べ替えられた数字: 1 3 5 9 42
数字: 1 42 3 9 5
デュレーション: 1 42 3 9 5
並べ替えられた期間: 1 42 3 9 5
デュレーション: 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 文字すべてを投稿できません。

私が間違っていること、またはこれが単に不可能な理由を誰かに説明してもらえますか (その場合)。

4

2 に答える 2

17

最初のエラーはかなり明確に見えます:

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<fordurationは関数テンプレートであり、その引数は から推測できないため、 への変換は行われませんreference_wrapper<duration<...>>

のインスタンスを渡すstd::less<std::chrono::milliseconds>std::sort、ラッパーが期間タイプに変換され、正しく比較されます。

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

millisecondsこれは基本的に、オブジェクトをnotと比較してソートすることを示していreference_wrapper<milliseconds>ます。

于 2016-04-01T12:39:02.147 に答える
5

@Niall の提案に従って、次lambdaのコンパレータとしてa を使用できます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(); } );
于 2016-04-01T12:44:00.973 に答える