So many asked this question, and no one came up with a satisfactory answer. Here is the std :: sort helper, which allows you to sort two vectors at a time, taking into account the values ββof only one vector. This solution is based on a custom RadomIt (random iterator) and works directly with the original vector data without temporary copies, structural rearrangement or additional indexes:
namespace std { namespace sort_helper { template <typename _Data, typename _Order> struct value_reference_t; template <typename _Data, typename _Order> struct value_t { _Data data; _Order val; inline value_t(_Data _data, _Order _val) : data(_data), val(_val) {} inline value_t(const value_reference_t<_Data,_Order>& rhs); }; template <typename _Data, typename _Order> struct value_reference_t { _Data* pdata; _Order* pval; value_reference_t(_Data* _itData, _Order* _itVal) : pdata(_itData), pval(_itVal) {} inline value_reference_t& operator = (const value_reference_t& rhs) { *pdata = *rhs.pdata; *pval = *rhs.pval; return *this; } inline value_reference_t& operator = (const value_t<_Data,_Order>& rhs) { *pdata = rhs.data; *pval = rhs.val; return *this; } inline bool operator < (const value_reference_t& rhs) { return *pval < *rhs.pval; } }; template <typename _Data, typename _Order> struct value_iterator_t : iterator< random_access_iterator_tag, value_t<_Data,_Order>, ptrdiff_t, value_t<_Data,_Order>*, value_reference_t<_Data,_Order> > { _Data* itData; _Order* itVal; value_iterator_t(_Data* _itData, _Order* _itVal) : itData(_itData), itVal(_itVal) {} inline ptrdiff_t operator - (const value_iterator_t& rhs) const { return itVal - rhs.itVal; } inline value_iterator_t operator + (ptrdiff_t off) const { return value_iterator_t(itData + off, itVal + off); } inline value_iterator_t operator - (ptrdiff_t off) const { return value_iterator_t(itData - off, itVal - off); } inline value_iterator_t& operator ++ () { ++itData; ++itVal; return *this; } inline value_iterator_t& operator -- () { --itData; --itVal; return *this; } inline value_iterator_t operator ++ (int) { return value_iterator_t(itData++, itVal++); } inline value_iterator_t operator -- (int) { return value_iterator_t(itData--, itVal--); } inline value_t<_Data,_Order> operator * () const { return value_t<_Data,_Order>(*itData, *itVal); } inline value_reference_t<_Data,_Order> operator * () { return value_reference_t<_Data,_Order>(itData, itVal); } inline bool operator < (const value_iterator_t& rhs) const { return itVal < rhs.itVal; } inline bool operator == (const value_iterator_t& rhs) const { return itVal == rhs.itVal; } inline bool operator != (const value_iterator_t& rhs) const { return itVal != rhs.itVal; } }; template <typename _Data, typename _Order> inline value_t<_Data,_Order>::value_t(const value_reference_t<_Data,_Order>& rhs) : data(*rhs.pdata), val(*rhs.pval) {} template <typename _Data, typename _Order> bool operator < (const value_t<_Data,_Order>& lhs, const value_reference_t<_Data,_Order>& rhs) { return lhs.val < *rhs.pval; } template <typename _Data, typename _Order> bool operator < (const value_reference_t<_Data,_Order>& lhs, const value_t<_Data,_Order>& rhs) { return *lhs.pval < rhs.val; } template <typename _Data, typename _Order> void swap(value_reference_t<_Data,_Order> lhs, value_reference_t<_Data,_Order> rhs) { std::swap(*lhs.pdata, *rhs.pdata); std::swap(*lhs.pval, *rhs.pval); } }
And this is a usage example that sorts both names and age based on age values ββusing standard std :: sort:
char* Names[] = { "Karl", "Paul", "Martin", "Jennie" }; int Age[] = { 45, 14, 5, 24 }; typedef std::sort_helper::value_iterator_t<char*,int> IndexIt; std::sort(IndexIt(Names, Age), IndexIt(Names+4, Age+4));
sorted by:
{ "Martin", "Paul", "Jennie", "Karl" }; { 5, 14, 24, 45 };
Verified code for Visual Studio 2017 and GCC 5.4.0.