Мне нужен код, чтобы проверить, является ли определенный шаблон частью пакета параметров.Чтобы реализовать проверку для нормальных классов, я использую подход, основанный на множественном наследовании, описанный, например, Луи Дионн здесь или Агустин Берже здесь .
Тестирование для класса
Идея состоит в том, что вы упаковываете каждый класс T
в пакете в класс PackEntry
, а затем PackIndex
наследует от всех PackEntry
классов,Таким образом, если вы ищете класс A
, все, что вам нужно сделать, это проверить, можно ли преобразовать PackIndex
в правильный PackEntry
.Сводя все воедино, это выглядит так:
#include <cstddef>
#include <utility>
template <class T>
struct PackEntry
{
using type = T;
};
template <class... Ts>
struct PackIndex : PackEntry<Ts>...
{};
template <class T, class... Ts>
struct PackSearcher
{
static constexpr std::false_type check(...);
// This overload is used if the PackIndex below
// derives from PackEntry<T>, the overload above
// otherwise.
static constexpr std::true_type check(PackEntry<T>);
using type =
decltype(check(PackIndex<Ts...>{}));
static constexpr bool
value()
{
return type{};
}
};
template <class... Ts>
struct Pack
{
template<class T>
static constexpr bool has() {
return PackSearcher<T, Ts...>::value();
}
};
int main() {
static_assert(Pack<int, void>::has<int>());
static_assert(! Pack<int, void>::has<bool>());
}
Тестирование для определенного шаблона
Теперь это все аккуратно, но скажите, что у меня есть шаблон Tmpl
, и я хочучтобы узнать, содержит ли мой пакет любую специализацию этого шаблона.Это легко сделать, если шаблон имеет определенную форму, скажем, template <std::size_t> class Tmpl {};
. По сути, единственное отличие состоит в том, что внутри PackSearcher
(который я сейчас называю TmplPackSearcher
, вы заставляете компилятор получать правильный параметр шаблона N
дляшаблон.
#include <cstddef>
#include <utility>
template <class T>
struct PackEntry
{
using type = T;
};
template <class... Ts>
struct PackIndex : PackEntry<Ts>...
{
};
template <template <std::size_t> class T, class... Ts>
struct TmplPackSearcher
{
static constexpr std::false_type check(...);
template <std::size_t N>
static constexpr std::true_type check(PackEntry<T<N>>);
using type =
decltype(check(PackIndex<Ts...>{}));
static constexpr bool
value()
{
return type{};
}
};
template <class... Ts>
struct Pack
{
template<template <std::size_t> class T>
static constexpr bool has_tmpl() {
return TmplPackSearcher<T, Ts...>::value();
}
};
template<std::size_t I>
class Tmpl {};
int main() {
static_assert(Pack<Tmpl<1>, int>::has_tmpl<Tmpl>());
static_assert(!Pack<int>::has_tmpl<Tmpl>());
}
Вопрос
Теперь мой вопрос: как проверить наличие шаблона в пакете параметров , не делая никаких предположений о том, как шаблонвыглядит как ? То есть я не хочу писать отдельный код для template<std::size_t>
, template<std::size_t, typename>
, template <typename, typename>
и т. д.
Бонусные баллы, если это можно сделать с использованием одного и того жеТрюк с наследованием.