Given the following concept
template <typename T>
concept HasID = requires(T t) {
{ t.get_id() } -> std::convertible_to<int>;
};
And the following classes
struct A { int get_id() { return 4; } };
struct B { int get_id() { return 5; } };
struct Router {
template <typename F>
void with_route(bool is_a, F&& f) {
if (is_a) {
f(std::get<A>(routes_));
} else {
f(std::get<B>(routes_));
}
}
std::tuple<A, B> routes_;
};
I’d like to be able to constrain the template type F
to indicate that it is a function that accepts an argument that satisfies the concept HasID
. Something like
template <typename F>
concept InvocableWithID = requires (F f) {
{ f(/* ??? */) };
};
And trying to add another template type like
template <typename F, typename Arg>
concept InvocableWithID = requires (F f, Arg arg) {
requires HasID<Arg>;
{ f(arg) };
};
Seems to defeat the purpose since the type of Arg
have to be specified at the declaration of the function but we don’t know if it’ll be A
or B
. In this example I suppose one could do
template <typename F>
concept InvocableWithID = requires (F f) {
{ f(A{}) };
{ f(B{}) };
};
But this only works if all possible HasID
types are known ahead of time which they are not in my case.