There is std::is_base_of
in modern STL. It allow us to determine whether the second parameter is derived from first parameter or if they are the same classes bo
If you can assume that a derived type uses a public inheritance from B
(and so the upcasting is possible), then you can use the following SFINAE:
namespace detail
{
template
struct is_derived_from_B
{
using U = typename std::remove_cv<
typename std::remove_reference::type
>::type;
template
static auto test(B*)
-> typename std::integral_constant>::value>;
static std::false_type test(void*);
using type = decltype(test(std::declval()));
};
}
template
using is_derived_from_B = typename detail::is_derived_from_B::type;
Tests:
static_assert(is_derived_from_B>::value, "!");
static_assert(!is_derived_from_B::value, "!");
static_assert(!is_derived_from_B>::value, "!");
static_assert(!is_derived_from_B>::value, "!");
DEMO 1
It can be generalized to accept any base class template:
namespace detail
{
template class Base, typename Derived>
struct is_derived_from_template
{
using U = typename std::remove_cv<
typename std::remove_reference::type
>::type;
template
static auto test(Base*)
-> typename std::integral_constant>::value>;
static std::false_type test(void*);
using type = decltype(test(std::declval()));
};
}
template class Base, typename Derived>
using is_derived_from_template
= typename detail::is_derived_from_template ::type;
Tests:
static_assert(is_derived_from_template>::value, "!");
static_assert(!is_derived_from_template::value, "!");
static_assert(!is_derived_from_template>::value, "!");
static_assert(!is_derived_from_template>::value, "!");
DEMO 2