Hier ist eine Beispielimplementierung, die einen neuen Iteratortyp definiert, um eine paarweise Ansicht über zwei Sequenzen bereitzustellen. Ich habe versucht, Standards konform und korrekt zu machen, aber da der C++ - Standard in seinen Details scheußlich komplex ist, bin ich mir fast sicher, dass ich gescheitert bin. Ich werde sagen, dass dieser Code scheint, wenn er mit clang++
oder g++
gebaut wird.
Dieser Code ist nicht empfohlen für den allgemeinen Gebrauch, da es länger und weniger verständlich ist als die anderen Antworten und möglicherweise ruft die gefürchtete 'undefined Verhalten'.
Allerdings, hat es den Vorteil der konstanten Zeit und Raum Overhead, da es eine Sicht auf vorhandene Daten bietet, anstatt tatsächlich eine temporäre alternative Darstellung oder Permutation Vektor zu erstellen. Das offensichtlichste (für mich) Leistungsproblem mit diesem Code ist, dass einzelne Elemente der beiden Container während des Swap-Vorgangs kopiert werden müssen.Trotz mehrerer Versuche habe ich keinen Weg gefunden, std::swap
erfolgreich zu spezialisieren, so dass std::sort
oder std::random_shuffle
die Verwendung der standardmäßigen temporär kopierbasierten Swap-Implementierung vermeidet. Es ist möglich, dass die Verwendung des Referenzwertsystems C++ 0x rvalue (siehe std::move
und Jon Purdys Antwort) dies lösen könnte.
#ifndef HDR_PAIRED_ITERATOR
#define HDR_PAIRED_ITERATOR
#include <iterator>
/// pair_view mostly looks like a std::pair,
/// and can decay to a std::pair, but is really a pair of references
template <typename ItA, typename ItB>
struct pair_view {
typedef typename ItA::value_type first_type;
typedef typename ItB::value_type second_type;
typedef std::pair<first_type, second_type> pair_type;
pair_view() {}
pair_view(const ItA &a, const ItB &b):
first(*a), second(*b) {}
pair_view &operator=(const pair_view &x)
{ first = x.first; second = x.second; return *this; }
pair_view &operator=(const pair_type &x)
{ first = x.first; second = x.second; return *this; }
typename ItA::reference first;
typename ItB::reference second;
operator pair_type() const
{ return std::make_pair(first, second); }
friend bool operator==(const pair_view &a, const pair_view &b)
{ return (a.first == b.first) && (a.second == b.second); }
friend bool operator<(const pair_view &a, const pair_view &b)
{ return (a.first < b.first) || ((a.first == b.first) && (a.second < b.second)); }
friend bool operator!=(const pair_view &a, const pair_view &b)
{ return !(a == b); }
friend bool operator>(const pair_view &a, const pair_view &b)
{ return (b < a); }
friend bool operator<=(const pair_view &a, const pair_view &b)
{ return !(b < a); }
friend bool operator>=(const pair_view &a, const pair_view &b)
{ return !(a < b); }
friend bool operator==(const pair_view &a, const pair_type &b)
{ return (a.first == b.first) && (a.second == b.second); }
friend bool operator<(const pair_view &a, const pair_type &b)
{ return (a.first < b.first) || ((a.first == b.first) && (a.second < b.second)); }
friend bool operator!=(const pair_view &a, const pair_type &b)
{ return !(a == b); }
friend bool operator>(const pair_view &a, const pair_type &b)
{ return (b < a); }
friend bool operator<=(const pair_view &a, const pair_type &b)
{ return !(b < a); }
friend bool operator>=(const pair_view &a, const pair_type &b)
{ return !(a < b); }
friend bool operator==(const pair_type &a, const pair_type &b)
{ return (a.first == b.first) && (a.second == b.second); }
friend bool operator<(const pair_type &a, const pair_type &b)
{ return (a.first < b.first) || ((a.first == b.first) && (a.second < b.second)); }
friend bool operator!=(const pair_type &a, const pair_type &b)
{ return !(a == b); }
friend bool operator>(const pair_type &a, const pair_type &b)
{ return (b < a); }
friend bool operator<=(const pair_type &a, const pair_type &b)
{ return !(b < a); }
friend bool operator>=(const pair_type &a, const pair_type &b)
{ return !(a < b); }
};
template <typename ItA, typename ItB>
struct paired_iterator {
// --- standard iterator traits
typedef typename pair_view<ItA, ItB>::pair_type value_type;
typedef pair_view<ItA, ItB> reference;
typedef paired_iterator<ItA,ItB> pointer;
typedef typename std::iterator_traits<ItA>::difference_type difference_type;
typedef std::random_access_iterator_tag iterator_category;
// --- methods not required by the Random Access Iterator concept
paired_iterator(const ItA &a, const ItB &b):
a(a), b(b) {}
// --- iterator requirements
// default construction
paired_iterator() {}
// copy construction and assignment
paired_iterator(const paired_iterator &x):
a(x.a), b(x.b) {}
paired_iterator &operator=(const paired_iterator &x)
{ a = x.a; b = x.b; return *this; }
// pre- and post-increment
paired_iterator &operator++()
{ ++a; ++b; return *this; }
paired_iterator operator++(int)
{ paired_iterator tmp(*this); ++(*this); return tmp; }
// pre- and post-decrement
paired_iterator &operator--()
{ --a; --b; return *this; }
paired_iterator operator--(int)
{ paired_iterator tmp(*this); --(*this); return tmp; }
// arithmetic
paired_iterator &operator+=(const difference_type &n)
{ a += n; b += n; return *this; }
friend paired_iterator operator+(const paired_iterator &x, const difference_type &n)
{ return paired_iterator(x.a+n, x.b+n); }
friend paired_iterator operator+(const difference_type &n, const paired_iterator &x)
{ return paired_iterator(x.a+n, x.b+n); }
paired_iterator &operator-=(const difference_type &n)
{ a -= n; b -= n; return *this; }
friend paired_iterator operator-(const paired_iterator &x, const difference_type &n)
{ return paired_iterator(x.a-n, x.b-n); }
friend difference_type operator-(const paired_iterator &x, const paired_iterator &y)
{ return (x.a - y.a); }
// (in-)equality and ordering
friend bool operator==(const paired_iterator &x, const paired_iterator &y)
{ return (x.a == y.a) && (x.b == y.b); }
friend bool operator<(const paired_iterator &x, const paired_iterator &y)
{ return (x.a < y.a); }
// derived (in-)equality and ordering operators
friend bool operator!=(const paired_iterator &x, const paired_iterator &y)
{ return !(x == y); }
friend bool operator>(const paired_iterator &x, const paired_iterator &y)
{ return (y < x); }
friend bool operator<=(const paired_iterator &x, const paired_iterator &y)
{ return !(y < x); }
friend bool operator>=(const paired_iterator &x, const paired_iterator &y)
{ return !(x < y); }
// dereferencing and random access
reference operator*() const
{ return reference(a,b); }
reference operator[](const difference_type &n) const
{ return reference(a+n, b+n); }
private:
ItA a;
ItB b;
};
template <typename ItA, typename ItB>
paired_iterator<ItA, ItB> make_paired_iterator(const ItA &a, const ItB &b)
{ return paired_iterator<ItA, ItB>(a, b); }
#endif
#include <vector>
#include <algorithm>
#include <iostream>
template <typename ItA, typename ItB>
void print_kvs(const ItA &k0, const ItB &v0, const ItA &kn, const ItB &vn) {
ItA k(k0);
ItB v(v0);
while (k != kn || v != vn) {
if (k != kn && v != vn)
std::cout << "[" << *k << "] = " << *v << "\n";
else if (k != kn)
std::cout << "[" << *k << "]\n";
else if (v != vn)
std::cout << "[?] = " << *v << "\n";
if (k != kn) ++k;
if (v != vn) ++v;
}
std::cout << std::endl;
}
int main() {
std::vector<int> keys;
std::vector<std::string> data;
keys.push_back(0); data.push_back("zero");
keys.push_back(1); data.push_back("one");
keys.push_back(2); data.push_back("two");
keys.push_back(3); data.push_back("three");
keys.push_back(4); data.push_back("four");
keys.push_back(5); data.push_back("five");
keys.push_back(6); data.push_back("six");
keys.push_back(7); data.push_back("seven");
keys.push_back(8); data.push_back("eight");
keys.push_back(9); data.push_back("nine");
print_kvs(keys.begin(), data.begin(), keys.end(), data.end());
std::cout << "Shuffling\n";
std::random_shuffle(
make_paired_iterator(keys.begin(), data.begin()),
make_paired_iterator(keys.end(), data.end())
);
print_kvs(keys.begin(), data.begin(), keys.end(), data.end());
std::cout << "Sorting\n";
std::sort(
make_paired_iterator(keys.begin(), data.begin()),
make_paired_iterator(keys.end(), data.end())
);
print_kvs(keys.begin(), data.begin(), keys.end(), data.end());
std::cout << "Sort descending\n";
std::sort(
make_paired_iterator(keys.begin(), data.begin()),
make_paired_iterator(keys.end(), data.end()),
std::greater< std::pair<int,std::string> >()
);
print_kvs(keys.begin(), data.begin(), keys.end(), data.end());
return 0;
}
Ich habe es nicht geschafft, zip_iterator für diese Art von Sortierung zu verwenden. Könntest du erklären, wie es geht? – twerdster