Skip to content

Instantly share code, notes, and snippets.

@sepastian
Last active September 29, 2023 13:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sepastian/12cef5143cc9df05d9a7652eb004a54e to your computer and use it in GitHub Desktop.
Save sepastian/12cef5143cc9df05d9a7652eb004a54e to your computer and use it in GitHub Desktop.
Multiple STL containers referencing same object in C++
#include <set>
#include <iostream>
#include <vector>
/*
* How to order a set<vector<A>::iterator>.
*/
struct A
{
int value;
A(int value): value(value){};
// When storing objects of this struct in an STL container,
// this operator will be used for ordering,
// e.g. set<A>.
//
// It will not be used to order set<vector<A>::iterator>;
// these will be ordered by pointer addresses.
bool operator<(const A& a) const {
return this->value < a.value;
}
};
int main()
{
// Vector holding struct objects: source of truth.
std::vector<A> v;
// Set holding iterators, without comparator.
// Appears unsorted, i.e. is sorted by pointer value, not by value inside struct.
std::set<std::vector<A>::iterator> s1;
// Set holding values, ordering uses "operator<" defined in struct A.
std::set<A> s2;
// Set holding iterators, with custom C++20 comparator.
// Ordered by value inside struct.
// From: https://stackoverflow.com/a/46128321/92049
auto cmp = [](std::vector<A>::iterator a, std::vector<A>::iterator b){ return a->value < b->value; };
std::set<std::vector<A>::iterator, decltype(cmp)> s3;
// Insert values into vector<A>.
v.push_back(A(1));
v.push_back(A(3));
v.push_back(A(2));
for (auto e: v) {
std::cout << e.value << " ";
}
std::cout << "=> vector<A>: " << std::endl;
// Insert element iterators into containers:
// set<vector<A>::iterator>
// set<A>
// set<vector<A>::iterator> + comparator
for (auto e=v.begin(); e!=v.end(); e++) {
s1.insert(e);
s2.insert(*e);
s3.insert(e);
}
// set<vector<A>::iterator> seems unordered;
// that's because it is ordered by poiner addresses.
for (auto e: s1) {
std::cout << e->value << " ";
}
std::cout << "=> set<vector<A>::iterator>: " << std::endl;
// set<A> is ordered by value,
// using operator<() from struct A
for (auto e: s2) {
std::cout << e.value << " ";
}
std::cout << "=> set<A>: " << std::endl;
// set<vector<A>::iterator> is ordered
// using custom comparator specified when creating the set.
for (auto e: s3) {
std::cout << e->value << " ";
}
std::cout << "=> set<vector<A>::iterator> + cmp: " << std::endl;
};
// Output:
// 1 3 2 => vector<A>:
// 1 3 2 => set<vector<A>::iterator>:
// 1 2 3 => set<A>:
// 1 2 3 => set<vector<A>::iterator> + cmp:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment