Допустимо ли использовать thrust::sort_by_key
, как в следующем коде?
#include <thrust/device_vector.h>
#include <thrust/sequence.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/sort.h>
#include <thrust/advance.h>
#include <thrust/copy.h>
#include <iterator>
#include <iostream>
int main()
{
int init[] = {2, 1, 0, 3, 4};
const thrust::device_vector< int > v{std::cbegin(init), std::cend(init)};
thrust::device_vector< std::intptr_t > index{v.size()};
thrust::sequence(index.begin(), index.end());
auto key = thrust::make_permutation_iterator(thrust::make_transform_iterator(v.cbegin(), thrust::identity< thrust::tuple< int > >{}), index.cbegin());
thrust::sort_by_key(key, thrust::next(key, index.size()), index.begin());
thrust::copy(index.cbegin(), index.cend(), std::ostream_iterator< std::intptr_t >(std::cout, ", "));
std::cout << std::endl;
}
Здесь index
массив указывает на v
массив значений. Я хочу иметь "отсортированный вид" ov v
. index
после сортировки выше - это представление, то есть сортируется [v[i] for i in index]
(псевдокод питона).
Трюк с преобразованием identity
имеет решающее значение: он преобразует значения, на которые указывает index
в v
в один элемент-кортеж. thrust::tuple
является классом и имеет operator =
, который не квалифицирован cv-ref только для lvalues и, таким образом, может использоваться для значений r, только что возвращенных в результате разыменования transform_iterator
. thrust::tuple< int >(1) = 2;
является юридическим заявлением и фактически является запретом, потому что значение левой части упало сразу после назначения. В результате все перестановки ключей в sort_by_key
являются бездействующими, а реальная сортировка происходит в части «значения» сортировки по ключу-значению.
Как я знаю, разработчики Thrust обычно предполагают, что все вызываемые объекты идемпотентная . Я полагаю, что предположение здесь не нарушается, потому что изменился только аргумент вызываемого (thrust::identity
), а не состояние вызываемого. Но, с другой стороны, любая суперпозиция причудливых итераторов Thrust может рассматриваться как композиция функций (скажем, permutation_iterator
- простое отображение).