Параллельная сортировка с помощью std::sort и пользовательского итератора, приводящего значения

#c #c 17

#c #c 17

Вопрос:

Я пишу метод сортировки, который сортирует два массива одновременно на основе значений в одном из массивов. Я использовал это в качестве ссылки и внес несколько незначительных изменений (сделал operator*() const и добавил конструкторы для класса ref ), поэтому он компилируется в MSVC / g / clang.

После добавления std::execution::par , чтобы включить параллельную сортировку, clang и g больше не компилируют ее (но MSVC это делает). Окончательный код и ошибку можно найти здесь . Ошибки в g и clang похожи:

источник:45:6: примечание: функция-кандидат нежизнеспособна: нет известного преобразования из ‘const val’ в ‘const ref’ для 1-го аргумента bool operator<(ref const amp; a, val const amp; b)

Эта ошибка может быть устранена путем реализации bool operator<(val constamp; a, val constamp; b) , но тогда массив конечных значений содержит пустые строки. Это можно решить, удалив move оператор from operator val() amp;amp; . Однако move оператор был важным дизайнерским решением для повышения производительности.

Вопрос: Есть ли способ сохранить оператор перемещения?

Итак, теперь он компилируется в онлайн-среде godbolt.org , но не локально, поскольку установка tbb влияет на этапы компиляции. Tbb устанавливается локально и необходим для фактического параллельного выполнения. Ошибка:

 /usr/include/c  /9/pstl/parallel_backend_tbb.h:435:1:   required from here
/usr/include/c  /9/bits/predefined_ops.h:215:11: error: no match for call to ‘(std::less<val>) (const refamp;, ref)’
  215 |  { return bool(_M_comp(__val, *__it)); }
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c  /9/string:48,
                 from tmp.cpp:2:
/usr/include/c  /9/bits/stl_function.h:385:7: note: candidate: ‘constexpr bool std::less<_Tp>::operator()(const _Tpamp;, const _Tpamp;) const [with _Tp = val]’ <near match>
  385 |       operator()(const _Tpamp; __x, const _Tpamp; __y) const
      |       ^~~~~~~~
/usr/include/c  /9/bits/stl_function.h:385:7: note:   conversion of argument 1 would be ill-formed:
In file included from /usr/include/c  /9/bits/stl_algobase.h:71,
                 from /usr/include/c  /9/vector:60,
                 from tmp.cpp:1:
/usr/include/c  /9/bits/predefined_ops.h:215:11: error: invalid user-defined conversion from ‘const ref’ to ‘const valamp;’ [-fpermissive]
  215 |  { return bool(_M_comp(__val, *__it)); }
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~
tmp.cpp:42:2: note: candidate is: ‘ref::operator val() amp;amp;’ <near match>
   42 |  operator val() amp;amp; { return {*key, *value}; }
      |  ^~~~~~~~
tmp.cpp:42:2: note:   passing ‘const ref’ as ‘this’ argument discards qualifiers
 

Дополнительный вопрос: почему он хочет выполнить преобразование, если он может использовать bool operator<(ref constamp; a, ref constamp; b) ?

Комментарии:

1. zip_iterator может вас заинтересовать (как boost )

2. Сверху, sort_it не соответствует требованиям итератора, и поэтому передача его std::sort показывает неопределенное поведение. » [forward.iterators]/1 Тип класса или указателя X удовлетворяет требованиям прямого итератора, если … если X является изменяемым итератором, reference является ссылкой на T ; если X является постоянным итератором, reference является ссылкой на const T » (где T есть value_type ).

3. @Jarod42 спасибо, что указали мне направление zip_operator . Я нашел интересное обсуждение stackexchange .