Подтвердить что ты не робот

Когда используется "typeid" лучшее решение?

Существует много причин не использовать typeid. Помимо использования членов type_info (поведение, определяемое реализацией), обычно (всегда?) Возможно обеспечить аналогичную функциональность, используя другие возможности языка С++, например: перегрузка, виртуальные функции и т.д.

Итак, исключая использование, которое зависит от поведения, определенного реализацией, есть ли у кого-нибудь пример реального мира, где typeid - лучшее решение?

4b9b3361

Ответ 1

boost::any использует typeid для реализации any_cast.

template<typename T> any_cast(const any& other) {
   if(typeid(T) != other.type()) throw bad_any_cast();

   //...actual cast here...
}

Вы не можете быть уверены, что T является полиморфным, поэтому dynamic_cast не может быть и речи, и закрытый тип в вызове boost::any уже потерян, поэтому ни одна из других трансляций не может предоставить какой-либо вид безопасности типа.

Ответ 2

Итак, исключая использование, которое зависит от поведения, определенного для реализации, есть ли у кого-нибудь пример реального мира, где typeid - лучшее решение?

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

Ответ 3

При реализации многотодовых (или нескольких отправлений), где фактический вызов выбирается из, например, карту, используя std::type_info* в качестве ключа.

Ответ 4

Напишите динамическое дерево, в котором вы можете на этапе выполнения изменить структуру дерева, где в каждой ссылке есть разные типы, для этого потребуется typeid. dynamic_cast недостаточно.

Изменить: Здесь несколько деталей:

class I {
public:
   virtual std::string type() const=0;
   virtual void *value() const=0;
};
template<class T>
class Impl : public I
{
public:
    Impl(T t) : t(t) { }
    std::string type() const { return typeid(T).name(); }
    void *value() const { return &t; }
private:
    T t;
};

И затем постройте дерево из них:

template<class Node, class Link>
class Tree { };

С типом ссылки, являющейся интерфейсом я *... Так как приведенное выше действие для любых значений типов T1, T2, T3, T4, мы могли бы также схожими классами для любых функций T- > T1, T- > T2, T- > T3, T- > T4 и использовать этот тип функции как Node дерева. Теперь у вас есть правильные выражения, описанные в динамическом дереве.

Ответ 5

Вы можете использовать typeid для сравнения фактических типов двух объектов. Может быть полезно, если вы хотите проверить равенство двух объектов и сначала убедитесь, что они одного и того же типа (хотя я должен сказать, что я не видел, чтобы это было сделано много, поэтому может быть веская причина, почему это не так хорошая идея...).

Ответ 6

Я использую его для проверки типа класса исключения в моем обработчике catch.

// fudge vtable existence (thrown exceptions must have one)
class StubException
{
    virtual ~StubException();
};

.....

catch(...)
{
    StubException *e = getExceptionObject(); // compiler/rt specific
    std::string s = typeid(e).name();

    ...

    throw;
}

Функция getExceptionObject() является частью небольшой библиотеки-утилиты, которую я неправильно использую для получения дополнительной информации об исключениях. Это очень удобно, когда функция генерирует исключение, которое я должен улавливать, но это не так. Это определенно сэкономило много разочарований на протяжении многих лет, так как я сразу же знаю тип исключения, которому требуется покрытие.