Разница между std :: is_base_of и std :: is_convertible - PullRequest
0 голосов
/ 13 марта 2019

Эти два шаблона, похоже, дают одинаковые результаты.Какая разница и когда мы должны использовать какие?

using namespace std;

class A {

};

class B : public A {

};

class C : public A {

};

int main()
{
    cout << boolalpha << is_convertible<B, A>::value << '\n';
    cout << boolalpha << is_base_of<A, B>::value << '\n';

    cout << boolalpha << is_convertible<B, C>::value << '\n';
    cout << boolalpha << is_base_of<C, B>::value << '\n';

    return 0;
}

После запуска программы я получил

true
true
false
false

Заранее спасибо!

1 Ответ

2 голосов
/ 15 марта 2019

Ознакомьтесь с документацией для 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 все еще работает.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...