I was trying to create a static interface using C++20 concepts, and the following code seems to do the job:
template <class FOO>
concept FooConcept = requires {
static_cast<void (FOO::*)(int)>(&FOO::operator());
static_cast<void (FOO::*)(char)>(&FOO::operator());
};
In particular, FooConcept
is satisfied by a class FOO
if such class overloads operator()
twice: with an int
argument and a char
argument, respectively.
This solution seems to work fine, but it doesn't look beautiful. Indeed, I would've liked much more the following forms:
template <class FOO>
concept FooConcept = requires (FOO foo, int i, char c) {
{ foo(i) } -> std::same_as<void>;
{ foo(c) } -> std::same_as<void>;
};
or
template <class FOO>
concept FooConcept = std::invocable<FOO, int> && std::invocable<FOO, char>;
However, these approaches don't work due to implicit conversions (see this post). Is there a better, more "semantic" way to express this constraint?