Search code examples
c++c++-concepts

Concepts: checking signatures of methods with arguments


I've been playing around with concepts. Here's a minimal example where I'm trying to create a concept based on method signatures:

template<typename T>
concept bool myConcept() {
    return requires(T a, int i) {
        { a.foo()   } -> int;
        { a.bar(i)  } -> int;
    };
}

struct Object {
    int foo()    {return 0;}
    int bar(int) {return 0;}
};

static_assert(myConcept<Object>(), "Object does not adhere to myConcept");

To my surprise writing { a.bar(int) } -> int did not work, so I resorted to adding an additional argument to the requires expression. This seems a bit strange and I was wondering if there is a way to do the same thing. Another thing that worked was using something like { a.bar((int)0) } -> int, but I find this worse.


Solution

  • Concepts check expressions, and a.bar(int) is not one. By writing

    { a.foo(int) } -> int
    

    you ask the compiler to check that the aforementioned expression has type int. Which doesn't make sense.

    You did find a valid alternative; another one might be, since the type of a.bar(x) doesn't depend on x' value:

    template<typename T>
    concept bool myConcept() {
        return requires(T a) {
            { a.foo()   } -> int;
            { a.bar(0)  } -> int;
        };
    }
    
    struct Object {
        int foo()    {return 0;}
        int bar(int) {return 0;}
    };
    
    static_assert(myConcept<Object>(), "Object does not adhere to myConcept");