C++17: Generic (multiple-inheritance based?) check for template in parameter pack

As @MaxLanghof mentioned in comments, it's not even possible to declare a has_tmpl that accept arbitrary kinds of templates. It's possible to have overloads of has_tmpl with different template parameters (template<std::size_t> class, template<std::size_t, typename> class, template <typename, typename> class, etc), but an infinite number of overloads are needed.

Instead, let's use a type that wraps the template, and expose everything we need. The simplest way AFAIK is (ab)using a lambda: []<std::size_t I>(type_identity<Tmpl<I>>){}.

And then the problem is almost trivial: has_tmpl can be simply defined to return (std::is_invocable_v<Lambda,type_identity<Ts>> || ...).

Complete example:

#include <type_traits>

template<class> struct type_identity {};

template <class... Ts>
struct Pack
{
    template<class Lambda>
    static constexpr bool has_tmpl(Lambda) {
        return (std::is_invocable_v<Lambda, type_identity<Ts>> || ...);
    }
};

template<std::size_t I>
class Tmpl {};

int main() {
    static_assert(Pack<Tmpl<1>, int>::has_tmpl([]<std::size_t I>(type_identity<Tmpl<I>>){}));
    static_assert(!Pack<int>::has_tmpl([]<std::size_t I>(type_identity<Tmpl<I>>){}));
}

Note that this uses a GNU extension that is standardized in C++20 (template-parameter-list for generic lambdas). I don't think this is avoidable.

It should be possible to use multiple inheritance, but fold expression is much shorter ;)