I can think of a simple transformation (well two) to get what you want. You could use std::transform
with suitable predicates.
std::vector<Thing>
to std::vector< std::pair<Result,Thing> >
- sort the second vector (works because a pair is sorted by it first member)
- reverse transformation
Tadaam :)
EDIT: Minimizing the number of copies
std::vector<Thing>
to std::vector< std::pair<Result,Thing*> >
- sort the second vector
- transform back into a secondary vector (local)
- swap the original and local vectors
This way you would only copy each Thing
once. Notably remember that sort
perform copies so it could be worth using.
And because I am feeling grant:
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);
}
Provided with the usual caveat emptor: off the top of my head, may kill kittens...