Recently had to do this. I ended up using pointers...
Quick Benchmark Results
#include <iostream>
#include <type_traits>
#include <algorithm>
#include <map>
#include <vector>
using map_t = std::map<int,int>;
const map_t m
{
{ 5, 20 },
{ -18, 28 },
{ 24, 49 },
{ 17, 27 },
{ 23, 46 },
{ 8, 16 },
{ -13, 11 },
{ -22, 32 },
{ 12, 45 },
{ -2, 19 },
{ 21, 11 },
{ -12, 25 },
{ -20, 8 },
{ 0, 29 },
{ -5, 20 },
{ 13, 26 },
{ 1, 27 },
{ -14, 3 },
{ 19, 47 },
{ -15, 17 },
{ 16, 1 },
{ -17, 50 },
{ -6, 40 },
{ 15, 24 },
{ 9, 10 }
};
template<typename T>
void sort_values_using_vector(T const& m)
{
using map_t = T;
using sort_t = std::vector<std::pair<typename map_t::key_type,
typename map_t::mapped_type>>;
sort_t sorted{ m.begin(), m.end() };
std::sort(sorted.begin(), sorted.end(),
[](auto const& lhs, auto const& rhs)
{
return lhs.second < rhs.second;
});
}
template<typename T>
void sort_values_using_multimap(T const& m)
{
using map_t = T;
using sort_t = std::multimap<typename map_t::mapped_type,
typename map_t::key_type>;
sort_t sorted;
for (auto const& kv : m)
{
sorted.insert(std::make_pair(kv.second, kv.first));
}
}
template<typename T>
void sort_values_using_ptrs(T const& m)
{
using map_t = T;
using ptr_t = std::add_pointer_t
<std::add_const_t<typename map_t::value_type>>;
using sort_t = std::vector<ptr_t>;
sort_t sorted;
sorted.reserve(m.size());
for (auto const& kv : m)
{
sorted.push_back(std::addressof(kv));
}
std::sort(sorted.begin(), sorted.end(),
[](auto const& lhs, auto const& rhs)
{
return lhs->second < rhs->second;
});
}
template<typename T>
void sort_values_using_refs(T const& m)
{
using map_t = T;
using ref_t = std::reference_wrapper
<std::add_const_t<typename map_t::value_type>>;
using sort_t = std::vector<ref_t>;
sort_t sorted{ m.begin(), m.end() };
std::sort(sorted.begin(), sorted.end(),
[](auto const& lhs, auto const& rhs)
{
return lhs.get().second < rhs.get().second;
});
}
static void copy_to_vector(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
sort_values_using_vector(m);
}
}
BENCHMARK(copy_to_vector);
static void copy_flipped_to_multimap(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
sort_values_using_multimap(m);
}
}
BENCHMARK(copy_flipped_to_multimap);
static void copy_ptrs_to_vector(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
sort_values_using_ptrs(m);
}
}
BENCHMARK(copy_ptrs_to_vector);
static void use_refs_in_vector(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
sort_values_using_refs(m);
}
}
BENCHMARK(use_refs_in_vector);