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