Я могу придумать простое преобразование (ну, два), чтобы получить то, что вы хотите. Вы можете использовать std::transform
с подходящими предикатами.
std::vector<Thing>
до std::vector< std::pair<Result,Thing> >
- отсортировать второй вектор (работает, потому что пара сортируется по первому члену)
- обратное преобразование
Тадаам:)
РЕДАКТИРОВАТЬ : Минимизация количества копий
std::vector<Thing>
до std::vector< std::pair<Result,Thing*> >
- сортировка по второму вектору
- преобразовать обратно во вторичный вектор (локальный)
- поменять местами оригинальные и локальные векторы
Таким образом, вы будете копировать каждый Thing
только один раз. Следует помнить, что sort
выполняет копии, чтобы его можно было использовать.
И потому что я чувствую себя дарованным:
typedef std::pair<float, Thing*> cached_type;
typedef std::vector<cached_type> cached_vector;
struct Compute: std::unary_function< Thing, cached_type >
{
cached_type operator()(Thing& t) const
{
return cached_type(CalculateGoodness(t), &t);
}
};
struct Back: std::unary_function< cached_type, Thing >
{
Thing operator()(cached_type t) const { return *t.second; }
};
void SortThings(std::vector<Thing>& things)
{
// Reserve to only allocate once
cached_vector cache; cache.reserve(things.size());
// Compute Goodness once and for all
std::transform(things.begin(), things.end(),
std::back_inserter(cache), Compute());
// Sort
std::sort(cache.begin(), cache.end());
// We have references inside `things` so we can't modify it
// while dereferencing...
std::vector<Thing> local; local.reserve(things.size());
// Back transformation
std::transform(cache.begin(), cache.end(),
std::back_inserter(local), Back());
// Put result in `things`
swap(things, local);
}
При условии обычного предостережения emptor: от макушки головы может убить котят ...