Consider the following toy example of an std::set
with a custom comparator:
#include <set>
struct A {
A() : a(cnt++) {}
const int a;
static int cnt;
};
int A::cnt = 0;
struct comp {
bool operator()(const A& left, const A& right)
{
return left.a < right.a;
}
};
int main()
{
std::set<A, comp> sa;
for (int i = 0; i < 10; ++i) sa.insert(A());
return 0;
}
Note that A
cannot simply be created from an integer.
I would like to look for an A
with a given value of A::a
in sa
, without constructing a temporary object of type A
, i.e. I am searching for something like
sa.find(4)
with a custom comparator that allows for direct comparison of integers with objects of type A
. Is that possible?
With C++14 you can utilize "transparent" comparator:
#include <iostream>
#include <set>
#include <type_traits>
class A
{
public: explicit A() : a{cnt++} {}
private: explicit A(int) = delete;
public: const int a;
private: static int cnt;
};
int A::cnt{};
class Comparator
{
// this member is required to let container be aware that
// comparator is capable of dealing with types other than key
public: using is_transparent = std::true_type;
public: bool operator()(const int & left, const A& right) const
{
return left < right.a;
}
public: bool operator()(const A & left, const int& right) const
{
return left.a < right;
}
public: bool operator()(const A& left, const A& right) const
{
return left.a < right.a;
}
};
int main()
{
std::set<A, Comparator> sa{};
for (int i{}; i < 10; ++i)
{
sa.emplace();
}
std::cout << sa.find(3)->a << std::endl;
return 0;
}
online compiler
Before C++14 heterogenous lookup was available in ::boost::intrusive::set
:
#include <boost/intrusive/set.hpp>
#include <iostream>
namespace bi = ::boost::intrusive;
// hook contains set node data, supports various options, can be a member
class A: public bi::set_base_hook
<
bi::link_mode<bi::link_mode_type::safe_link>
>
{
public: explicit A() : a{cnt++} {}
private: explicit A(int) = delete;
public: const int a;
private: static int cnt;
};
int A::cnt{};
class Comparator
{
public: bool operator()(const int & left, const A& right) const
{
return left < right.a;
}
public: bool operator()(const A & left, const int& right) const
{
return left.a < right;
}
public: bool operator()(const A& left, const A& right) const
{
return left.a < right.a;
}
};
int main()
{
bi::set<A, bi::compare<Comparator>> sa{Comparator{}};
for (int i{0}; i < 10; ++i)
{
sa.insert(*new A{}); // typically user manages object creation
}
// comparators may vary
std::cout << sa.find(3, Comparator{})->a << std::endl;
return 0;
}
online compiler
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With