2016-11-18 5 views
4

В этой программе я использую TypeId проверить производный тип объекта:Сравнение TypeID указатели

#include <cstdint> 
#include <memory> 
#include <cassert> 
#include <string> 
#include <typeinfo> 

struct Wrap 
{ 
    explicit Wrap(int64_t id) : mImpl(new Impl<int64_t>(id)) {} 

    explicit Wrap(std::string id) : mImpl(new Impl<std::string>(std::move(id))) {}  

    bool isInt64() const 
    { 
     const ImplBase& impl = *mImpl; 
     return (&typeid(impl) == &typeid(const Impl<int64_t>)); 
    }  

    bool isString() const 
    { 
     const ImplBase& impl = *mImpl; 
     return &typeid(impl) == &typeid(const Impl<std::string>); 
    } 

private: 
    struct ImplBase 
    { 
     virtual ~ImplBase() {} 
    }; 

    template<typename T> 
    struct Impl : ImplBase 
    { 
     Impl(T value) : 
      mValue(std::move(value)) 
     { 
     } 

     T mValue; 
    }; 

    std::shared_ptr<const ImplBase> mImpl; 
}; 

int main() 
{ 
    Wrap r1(int64_t(1)); 
    assert(r1.isInt64()); 

    Wrap r2(std::string("s")); 
    assert(r2.isString()); 
} 

Это похоже на работу, однако, я волнуюсь, что это не может работать на всех платформах. Кроме того, я не уверен, если я должен использовать:

typeid(const Impl<std::string>&) // with ref 

вместо

typeid(const Impl<std::string>) // without ref 

в функции сравнения.

Правильный ли приведенный выше код? Если нет, то как я могу это исправить?

+0

Почему поле typeid в VT хранит ссылочный тип? – Arunmu

+0

@Arunmu хороший момент, я не думал об этом. – StackedCrooked

ответ

5

При использовании typeid его можно применять к выражению или типу. При применении к типу, как у вас есть:

Относится к объекту std :: type_info, представляющему тип типа. Если тип является ссылочным типом, результат относится к объекту std :: type_info , представляющему ссылочный тип.

http://en.cppreference.com/w/cpp/language/typeid. Поэтому не имеет значения, используете ли вы ссылку. Тот же источник продолжает говорить:

Там нет никакой гарантии, что тот же станд :: type_info экземпляра будет упоминаться всеми оценками выражения TypeID на тот же типа, хотя станд :: type_info :: hash_code этих объектов type_info будет идентичным, как и их std :: type_index.

Это означает, что сравнение &typeid(impl) с чем-то другим может привести к ошибке, даже если объект имеет тот же динамический тип. Таким образом, это не такой хороший выбор для сравнения их адресов. Вы сами должны сравнить сами объекты непосредственно, т. Е. Просто удалить оператора & с обеих сторон, потому что std::type_info (возвращается typeid) имеет operator==.

Смежные вопросы