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?
With some helper, and with non- final
classes, you might do:
template <typename T>
struct DeletedOperator : T
{
using T::operator ();
template <typename ... Ts>
void operator()(Ts&&...) = delete;
template <typename ... Ts>
void operator()(Ts&&...) const = delete;
};
template <class FOO>
concept FooConcept = requires (DeletedOperator<FOO> foo, int i, char c) {
{ foo(i) } -> std::same_as<void>;
{ foo(c) } -> std::same_as<void>;
};
I think we can get rid of the non- final
constraint by adjusting the helper.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.