Ознакомьтесь с документацией для std::is_base_of
и std::is_convertible
.
Вот некоторые различия:
#include <type_traits>
struct anything_can_convert_to {
// This constructor constructs from anything
template<class T> anything_can_convert_to(T&&) {}
};
struct can_convert_to_anything {
// This conversion operator can convert to anything
template<class T> operator T() { return *static_cast<T*>(nullptr); }
};
struct cant_convert_to_base;
struct base {
base(const cant_convert_to_base&) = delete;
};
struct public_derived : base {};
struct private_derived : private base {};
struct cant_convert_to_base : base {};
int main() {
#define IS_CONVERTIBLE(FROM, TO) static_assert(std::is_convertible_v<FROM, TO>)
#define IS_NOT_CONVERTIBLE(FROM, TO) static_assert(!std::is_convertible_v<FROM, TO>)
#define IS_BASE_OF(BASE, DERIVED) static_assert(std::is_base_of_v<BASE, DERIVED>)
#define IS_NOT_BASE_OF(BASE, DERIVED) static_assert(!std::is_base_of_v<BASE, DERIVED>)
IS_CONVERTIBLE(int, long);
IS_CONVERTIBLE(int, anything_can_convert_to);
IS_CONVERTIBLE(can_convert_to_anything, int);
IS_NOT_CONVERTIBLE(anything_can_convert_to, int);
IS_CONVERTIBLE(public_derived, base);
IS_NOT_CONVERTIBLE(private_derived, base);
IS_NOT_CONVERTIBLE(cant_convert_to_base, base);
IS_NOT_BASE_OF(int, long);
IS_NOT_BASE_OF(int, anything_can_convert_to);
IS_BASE_OF(base, public_derived);
IS_BASE_OF(base, private_derived);
IS_BASE_OF(base, cant_convert_to_base);
}
Вы поймете, что они для двух разных вещей. std::is_base_of<Base, Derived>
делает именно то, на что это похоже: является ли Base
базовым классом Derived
, с точки зрения наследования. std::is_convertible<From, To>
в основном проверяет, если:
To test = (expression of type From);
хорошо сформирован. Для наследования это в основном случай, если From
является базовым классом To
, но есть много других ситуаций, где это так (например, при частном наследовании вы не можете преобразовать в базовый, но std::is_base_of
все еще работает.)