Сравнение базовых (производных) типов, на которые указывает std::unique_ptr

Я пишу модульные тесты для проверки различных путей кода с участием фабричного класса.

Фабрика возвращает std::unique_ptr базовому типу:

class Base {};
class Derived1 : public class Base {};
class Derived2 : public class Base {};

std::unique_ptr<Base> Type::Factory(enum rtype) const {
    switch(rtype) {
        case d1: return std::make_unique<Derived1>();
        case d2: return std::make_unique<Derived2>();
        default: return std::make_unique<Derived1>();
    }
}

Поэтому в тесте я хочу убедиться, что возвращается правильный тип (фабрики являются рассадником ошибок вырезания и вставки).

Есть ли способ проверить, какой тип возвращается? Это: EXPECT_TRUE(typeid(Derived1), typeid(type.get()); ложно, потому что type.get() принадлежит Base, а не rtype, которое было передано.


person graham.reeds    schedule 15.06.2020    source источник
comment
Я ожидаю, что если вы сделаете typeid(*type.get()), он проверит динамический тип, нет?   -  person underscore_d    schedule 15.06.2020
comment
Отвечает ли это на ваш вопрос? Получить тип объекта из указателя на базовый класс во время выполнения Второй ответ говорит о том, чтобы разыменовать указатель, как я предложил.   -  person underscore_d    schedule 15.06.2020
comment
То, что default возвращает Derived1, выглядит пугающе.   -  person Ted Lyngmo    schedule 15.06.2020
comment
@underscore_d Это работает. Я искал сравнение базовых типов, и это не было ссылкой.   -  person graham.reeds    schedule 15.06.2020


Ответы (2)


Это: EXPECT_TRUE(typeid(Derived1), typeid(type.get()); это false, потому что type.get() принадлежит Base, а не rtype, которое было передано.

typeid( type.get() ) получит typeid базового указателя, то есть тип, который get() объявлен как возвращаемый. Чтобы получить реальный динамический тип объекта, на который указывает указатель, каким бы он ни был, вы должны разыменовать указатель:

typeid( *type.get() )

person underscore_d    schedule 15.06.2020

Вам нужно использовать RTTI. При использовании тип стирается до Base.

Вы можете выполнить динамическое приведение, чтобы получить правильный тип, например:

EXPECT_FALSE(dynamic_cast<Derived1*>(type.get()) == nullptr)

В случае сбоя dynamic_cast (тип не Derived1) dynamic_cast вернет nullptr.

person Mikael H    schedule 15.06.2020