I have the following:
struct Base {};
struct Derived : public Base {};
struct DualHandler {
static void handle(Base&) {}
static void handle(Derived&) {}
};
struct SingleHandler {
static void handle(Base&) {}
};
I want to define a concept that is satisfied by DualHandler
but not by SingleHandler
. How can I do this?
My naive attempt is:
template<typename T>
concept IsDualHandler = requires(Base& b, Derived& d) {
{ T::handle(b) };
{ T::handle(d) };
};
But unfortunately, SingleHandler
satisfies IsDualHandler
, because a Derived&
can be passed to any function that expects a Base&
.
template<class T>
struct be_exactly {
template<class U> requires (std::same_as<std::decay_t<T>,std::decay_t<U>>)
operator U&();
};
this tries to match a function argument only exactly.
template<typename T>
concept IsDualHandler = requires(be_exactly<Base> b, be_exactly<Derived> d) {
{ T::handle(b) };
{ T::handle(d) };
};
this distinguishes them.
I don't like it being references hard coded; you can fix that with way too much boilerplate.