2016-11-18 96 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

爲什麼VT中的typeid字段存儲引用類型? – Arunmu

+0

@阿努木好點,我沒有考慮過。 – StackedCrooked

回答

5

使用typeid時,它可以應用於表達式或類型。當應用於某種類型時,如您所用:

引用表示類型類型的std :: type_info對象。如果類型 是引用類型,則結果引用表示引用類型的std :: type_info對象 。

http://en.cppreference.com/w/cpp/language/typeid。所以不管你是否使用這個參考,它都沒有什麼區別。同一消息來源繼續說:

沒有保證相同的std :: TYPE_INFO實例將通過在同一 類型的typeid表達的所有評價被稱爲,雖然的std :: TYPE_INFO ::那些type_info對象 的hash_code應該是相同的,就像他們的std :: type_index一樣。

這意味着,將&typeid(impl)與其他值進行比較,即使對象具有相同的動態類型也可能返回false。因此,比較他們的地址並不是一個好的選擇。您應該直接比較對象本身,即從兩側刪除&運算符,因爲std::type_info(由typeid返回)已定義operator==