Используя SFINAE, это может быть решено следующим образом
template <class, class = void>
struct is_foo_bar : std::false_type { };
template <class T>
struct is_foo_bar<
T,
std::enable_if_t<
std::is_same_v< T, typename foo<T::f>::template bar<T::b> >
>
> : std::true_type { };
Это работает, но вам нужно явно указать все аргументы, что может быть проблемой (например, для переменных).
РЕДАКТИРОВАТЬ : Найдена подсказка для вариативных аргументов
template <int F>
struct foo
{
template <int B, class... Params>
struct bar {
static constexpr int f = F;
static constexpr int b = B;
static constexpr size_t size = sizeof...(Params);
};
};
template <class, class = void>
struct is_foo_bar : std::false_type { };
template <template <int, class...> class T, int B, class... Params>
struct is_foo_bar<
T<B, Params...>,
std::enable_if_t<
std::is_same_v<
T<B, Params...>,
typename foo< T<B, Params...>::f >::template bar<B, Params...>
>
>
> : std::true_type { };
template <int, class...>
struct not_foo_bar {
static constexpr int f = 0;
};
static_assert(is_foo_bar< foo<1>::bar<2> >::value);
static_assert(is_foo_bar< foo<1>::bar<2, int> >::value);
static_assert(not is_foo_bar< not_foo_bar<1> >::value);
static_assert(not is_foo_bar< not_foo_bar<1, int> >::value);
Это гарантирует, что bar
принадлежит foo
.Когда такого требования нет, должно быть менее уродливо просто проверить наличие необходимых членов с std::void_t
и std::declval
...