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

C++ Concepts: checking for template instantiation


Assuming I have a templated type, e.g.

template<typename A, typename B, typename C>
struct mytype { };

How do I write a concept that checks whether a type is an instantiation of that template?

template<typename T>
concept MyType = requires(T x) { ??? }

I can't figure an obvious way of doing it without resolving to old-style specialised detector types or maybe a marker base type.


Solution

  • Using C++17 class template argument deduction, you should be able to do something like this:

    template<typename A, typename B, typename C>
    struct mytype { };
    
    template<class T>
    concept C1 = requires(T x) { 
        { mytype{x} } -> std::same_as<T>;
    };
    

    mytype{x} uses class template argument deduction to deduce A, B and C, so this is valid if you can construct a mytype<A, B, C> from a T. In particular, this is valid if mytype is copy-constructible since you have an implicitly declared copy-deduction guide similar to:

    template <typename A, typename B, typename C>
    mytype(mytype<A, B, C>) -> mytype<A, B, C>;
    

    Checking that T is also the constructed mytype instantiation avoid matching other deduction guides, e.g., this would match for any type without the -> std::same_as<T>:

    template <class A, class B, class C>
    struct mytype {
        mytype(A);
    };
    
    template <class A>
    mytype(A) -> mytype<A, A, A>;
    

    The proposed solution does not work for non copy-constructible classes, even though should be possible to make it work for move-only classes.


    Tested with and : https://godbolt.org/z/ojdcrYqKv