Reputation: 34393
If I understand it correctly, both std::map and std::unordered_map store keys explicitely (store pairs of keys / values). Is there some other ready to use container (std, boost or other widespread implementation) which would not store the key, but rather allow deriving the key from the stored value using a function (i.e. to use implicit key?).
Upvotes: 6
Views: 338
Reputation: 2129
All ordered containers in C++ library e.g. std::set
allow for less comparison template trait, pass it as a second template parameter (my_less
in example below). . If you don't do it, operator<
will be looked up via ADL and used if found (compilation error if not); it should be appropriate for plenty of cases.
Your own trait or operator<
can be used to define order according to data stored in a set i.e. without key. No data is copied to perform this comparison, please note it takes const references.
If you don't want to create stack object and prefer to use heap pointers instead, you can obviously store boost::shared_ptr
in standard ordered container and write your less comparison trait accordingly. In this case you may also consider using boost ptr containers
Example:
#include <boost/shared_ptr.hpp>
#include <set>
#include <iterator>
#include <iostream>
struct order_by_AB { int a; int b; int c;
order_by_AB(int a, int b, int c) : a(a), b(b), c(c) {}
};
struct my_less
{
bool operator()(const boost::shared_ptr<order_by_AB>& lh, const boost::shared_ptr<order_by_AB>& rh)
{
if (lh->a == rh->a)
return lh->b < rh->b;
return lh->a < rh->a;
}
};
std::ostream& operator<< (std::ostream& os, const boost::shared_ptr<order_by_AB>& rh)
{
os << "(" << rh->a << "," << rh->b << "," << rh->c << ")";
return os;
}
int main()
{
std::set<boost::shared_ptr<order_by_AB>, my_less> data;
data.insert(boost::shared_ptr<order_by_AB>(new order_by_AB(0, 1, 2)));
data.insert(boost::shared_ptr<order_by_AB>(new order_by_AB(2, 3, 2)));
data.insert(boost::shared_ptr<order_by_AB>(new order_by_AB(0, 3, 2)));
data.insert(boost::shared_ptr<order_by_AB>(new order_by_AB(2, 1, 2)));
std::copy(data.begin(), data.end(), std::ostream_iterator<boost::shared_ptr<order_by_AB>>(std::cout, "\n"));
return 0;
}
Edited to give example of user-specified functor for comparison.
Edited to add boost::shared_ptr
in a container
Upvotes: 0
Reputation: 254431
std::set
or std::unordered_set
, with suitable hash and/or comparison functions for the stored value type.
However, lookup will be done by the stored value type, not the key, so you'll also need a way to fabricate a temporary object from a key.
Upvotes: 4
Reputation: 39208
You might be looking for Boost.Intrusive. Boost Intrusive containers "hook into" your value types to provide the characteristics of a certain container (e.g. set, list, AVL tree, etc.) directly from the objects.
See Differences between intrusive and non-intrusive containers for an overview of the differences between STL containers and Boost Intrusive containers.
Upvotes: 2