Если вы можете предположить, что производный тип использует открытое наследование от B<Args...>
(и поэтому приведение к базовому типу возможно), то вы можете использовать следующую SFINAE:
namespace detail
{
template <typename Derived>
struct is_derived_from_B
{
using U = typename std::remove_cv<
typename std::remove_reference<Derived>::type
>::type;
template <typename... Args>
static auto test(B<Args...>*)
-> typename std::integral_constant<bool
, !std::is_same<U, B<Args...>>::value>;
static std::false_type test(void*);
using type = decltype(test(std::declval<U*>()));
};
}
template <typename Derived>
using is_derived_from_B = typename detail::is_derived_from_B<Derived>::type;
Тесты:
static_assert(is_derived_from_B<const D<int, char, float>>::value, "!");
static_assert(!is_derived_from_B<int>::value, "!");
static_assert(!is_derived_from_B<B<int,int>>::value, "!");
static_assert(!is_derived_from_B<std::vector<int>>::value, "!");
DEMO 1
Это может быть обобщена принять любую базу Шаблон класса:
namespace detail
{
template <template <typename...> class Base, typename Derived>
struct is_derived_from_template
{
using U = typename std::remove_cv<
typename std::remove_reference<Derived>::type
>::type;
template <typename... Args>
static auto test(Base<Args...>*)
-> typename std::integral_constant<bool
, !std::is_same<U, Base<Args...>>::value>;
static std::false_type test(void*);
using type = decltype(test(std::declval<U*>()));
};
}
template <template <typename...> class Base, typename Derived>
using is_derived_from_template
= typename detail::is_derived_from_template<Base, Derived>::type;
Тесты:
static_assert(is_derived_from_template<B, const D<int, int>>::value, "!");
static_assert(!is_derived_from_template<B, int>::value, "!");
static_assert(!is_derived_from_template<B, B<int, int>>::value, "!");
static_assert(!is_derived_from_template<B, std::vector<int>>::value, "!");
DEMO 2
@Nim Как его использовать? Имеет ли он достаточные отличия от стандартной черты типа std :: is_base_of? – Orient
Извините, только что понял ваш вопрос после переформатирования, проигнорируйте форсированную часть комментария. – Nim
Я думаю, что-то вроде 'template constexpr std :: true_type helper (B < types... > const &); template constexpr std :: false_type helper (T &&); decltype (helper (std :: declval < D const & >())) возможно, если разрешена такая перегрузка. –
Orient