Search code examples
c++c++20c++-concepts

Is there any way to pass C++ concepts themselves?


template<class S>
using Floating1 = std::is_floating_point<S>;
template<class S>
concept Floating2 = std::is_floating_point_v<S>;

You can pass Floating1...

template<template<class...> class F> struct TType {
    template<class... S> using type = F<S...>;
};
using X = TType<Floating1>;
//...
template<class S> using Y = typename X::template type<S>;

So what about Floating2? You can call a function that distinguishes a Floating2 if you know that's what you're looking for, just like instantiating Floating1<S>; but how do you pass Floating2 like TType<Floating1>?

I highly suspect that it can't be done, any more than you can pass class or auto.

As a possible use case, functions like std::invoke have variants that let you specify a return type. It would be great if that return type could be a constrained auto. Can any function, template, etc. accept a concept, outside of concepts/requirements themselves?

Or you could write two helper functions, one using the concept and one not, for each and every concept you want to consider. There has to be a better way.


Solution

  • No, concepts can't be passed as template (or any other kind of) arguments.

    As a possible use case, functions like std::invoke have variants that let you specify a return type. It would be great if that return type could be a constrained auto. Can any function, template, etc. accept a concept, outside of concepts/requirements themselves?

    The caller of std::invoke can already achieve the exact same behavior that this would have at the call site, i.e.

    SomeConcept auto ret = std::invoke(/*...*/);
    

    This will produce an error if the return value doesn't satisfy SomeConcept. That's all a constraints on a return type of std::invoke would do as well.

    I suspect this wasn't considered as a feature because there aren't any or many use cases that would actually profit over the current situation.