Lessi
Lessi

Reputation: 175

c++ requires expression with inverse return type concept check

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

Answers (2)

nhatnq
nhatnq

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

super
super

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())>;
};

Demo

It a bit harder to read. Maybe someone with some more experience with concepts can provide a better solution.

Upvotes: 7

Related Questions