Reputation: 175
I try to define a concept with a requires expression which checks some member function existence on the type.
The problem I run into is, that a single concept has to be plugged in for the return type check without any preceding bool operations like "not". This forces me to also write concepts for the inverse if needed, which is not really handy.
Is there something I am missing or another good way to do it?
Simple example:
template <typename T>
concept IsReference = std::is_reference_v<T>;
template <typename T>
concept HasSomeFunction = requires (T t) {
{t.func()} -> IsReference; /* this is ok */
{t.anotherFunc()} -> (not IsReference); /* this is not ok */
};
Upvotes: 6
Views: 1552
Reputation: 1193
Try this
#include <memory>
#include <cassert>
struct B {};
struct D : B {};
template <typename T>
concept IsReference = std::is_reference_v<T>;
template <typename T>
concept NotIsReference = !std::is_reference_v<T>;
template <typename T>
concept HasSomeFunction = requires (T t) {
{t.func()} -> IsReference;
{t.anotherFunc()} -> NotIsReference;
};
int main() {
std::shared_ptr<B> b = std::make_shared<D>();
auto d = static_pointer_cast<D>(b);
assert(d);
}
Upvotes: 0
Reputation: 12938
Here is a syntax that works on latest gcc and clang.
template <typename T>
concept HasSomeFunction = requires (T t) {
{t.func()} -> IsReference; /* this is ok */
requires !IsReference<decltype(t.anotherFunc())>;
};
It a bit harder to read. Maybe someone with some more experience with concepts can provide a better solution.
Upvotes: 7