std::is_base_of (3) - Linux Manuals

std::is_base_of: std::is_base_of


std::is_base_of - std::is_base_of


Defined in header <type_traits>
template< class Base, class Derived > (since C++11)
struct is_base_of;

If Derived is derived from Base or if both are the same non-union class (in both cases ignoring cv-qualification), provides the member constant value equal to true. Otherwise value is false.
If both Base and Derived are non-union class types, and they are not the same type (ignoring cv-qualification), Derived shall be a complete_type; otherwise the behavior is undefined.

Helper variable template

template< class Base, class Derived > (since C++17)
inline constexpr bool is_base_of_v = is_base_of<Base, Derived>::value;

Inherited from std::integral_constant

Member constants

value true if Derived is derived from Base or if both are the same non-union class (in both cases ignoring cv-qualification), false otherwise
         (public static member constant)

Member functions

              converts the object to bool, returns value
operator bool (public member function)

operator() returns value
              (public member function)

Member types

Type Definition
value_type bool
type std::integral_constant<bool, value>


std::is_base_of<A, B>::value is true even if A is a private, protected, or ambiguous base class of B. In many situations, std::is_convertible<B*, A*> is the more appropriate test.
Although no class is its own base, std::is_base_of<T, T>::value is true because the intent of the trait is to model the "is-a" relationship, and T is a T. Despite that, std::is_base_of<int, int>::value is false because only classes participate in the relationship that this trait models.

Possible Implementation

  namespace details {
      template <typename Base> std::true_type is_base_of_test_func(const volatile Base*);
      template <typename Base> std::false_type is_base_of_test_func(const volatile void*);
      template <typename Base, typename Derived>
      using pre_is_base_of = decltype(is_base_of_test_func<Base>(std::declval<Derived*>()));

      // with <experimental/type_traits>:
      // template <typename Base, typename Derived>
      // using pre_is_base_of2 = std::experimental::detected_or_t<std::true_type, pre_is_base_of, Base, Derived>;
      template <typename Base, typename Derived, typename = void>
      struct pre_is_base_of2 : public std::true_type { };
      // note std::void_t is a C++17 feature
      template <typename Base, typename Derived>
      struct pre_is_base_of2<Base, Derived, std::void_t<pre_is_base_of<Base, Derived>>> :
          public pre_is_base_of<Base, Derived> { };

  template <typename Base, typename Derived>
  struct is_base_of :
      public std::conditional_t<
          std::is_class<Base>::value && std::is_class<Derived>::value,
          details::pre_is_base_of2<Base, Derived>,
      > { };


// Run this code

  #include <iostream>
  #include <type_traits>

  class A {};

  class B : A {};

  class C {};

  int main()
      std::cout << std::boolalpha;
      std::cout << "a2b: " << std::is_base_of<A, B>::value << '\n';
      std::cout << "b2a: " << std::is_base_of<B, A>::value << '\n';
      std::cout << "c2b: " << std::is_base_of<C, B>::value << '\n';
      std::cout << "same type: " << std::is_base_of<C, C>::value << '\n';


  a2b: true
  b2a: false
  c2b: false
  same type: true

See also

is_nothrow_convertible checks if a type can be converted to the other type
                       (class template)