2010-04-21 67 views
0

在我的應用程序中,有一個繼承層次結構,其中只有位於繼承鏈末尾的類是非抽象類。還有一些boost :: variant的用法。我想寫一個函數,它需要一個指針和一個類型,並說明對象是否屬於該類型。確定類型

例如

#define IsA(nodeptr, type) (checkType<type>(nodeptr)) 

template<typename Type, bool isAbstract, typename PtrType > 
class CheckType 
{ 
    bool operator()(PtrType* ptr) { return (typeid(*ptr) == typeid(Type)); } 
}; 

template<typename Type, typename PtrType > 
class CheckType < Type, true, PtrType > 
{ 
    bool operator()(PtrType* ptr) { return (dynamic_cast<Type*>(ptr) != NULL); } 
}; 

template<typename Type, BOOST_VARIANT_ENUM_PARAMS(typename T) > 
class CheckType< Type, false, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > 
{ 
    bool operator()(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>* ptr) 
    { 
     return (ptr->type() == typeid(Type)); 
    } 
} 

template< typename Type, typename PtrType > 
bool checkType(PtrType* nodePtr) 
{ 
    CheckType<Type, boost::is_abstract<PtrType>::value, PtrType> check; 
    return check(nodePtr); 
} 

現在如果有一個升壓變型,我想找出是否升壓變存儲特定類型。有人可以幫助我嗎?我不想添加額外的參數來確定它是否是變體。即使找出抽象性,我使用boost :: is_abstract ..

謝謝, Gokul。

+0

does dynamic_cast是否爲您填寫賬單? – 2010-04-21 15:08:23

+0

我們想盡可能使用typeid來代替動態投射。 Boost :: Variant不適用於動態轉換 – Gokul 2010-04-22 04:46:45

回答

4

那麼有兩個直接的版本是:

return (boost::get<Type*>(v) != 0); 

而且這樣的:

return (v.type() == typeid(Type)); 

我不知道如何處理與您的模板重載乾淨,但你可以做這樣的事情:

template< typename Type, bool TypeisAbstract, bool TypeIsVariant, 
      typename ptrType > 
bool checkType(ptrType* t) 
{ 
    return (typeid(*t) == typeid(Type)); 
} 

template< typename Type, typename ptrType > 
bool checkType<Type, true, false, ptrType>(ptrType* t) 
{ 
    return (dynamic_cast<Type*>(t) != NULL); 
} 

template< typename Type> 
bool checkType<Type, false, true, ptrType>(const boost::variant& v) 
{ 
    return (v.type() == typeid(Type)); 
} 
+0

我想要在不添加模板參數的情況下進行說明,以確定它是否是變體... – Gokul 2010-04-21 15:14:19

+0

哦!我忽略了類型()函數的變體謝謝 – Gokul 2010-04-21 15:31:50

2

處理Boost.Variant最徹底的方法通常是使用訪客。

template <class Type> 
class TypeChecker: boost::static_visitor<> 
{ 
public: 
    explicit TypeChecker(bool& result): mResult(result) {} 

    template <class T> 
    void operator()(const T& t) const { mResult = dynamic_cast<const Type*>(&t); } 

private: 
    bool& mResult; 
}; 

然後你就可以把它包裝:

template <class Type, class Variant> 
bool checkType(const Variant& v) 
{ 
    bool result = false; 
    boost::apply_visitor(TypeChecker<Type>(result), v); 
    return result; 
} 

其中可用於像這樣:

int main(int argc, char* argv[]) 
{ 
    typedef boost::variant<Dog,Cat,Kid> variant_type; 

    variant_type var = /**/; 

    if (checkType<Animal>(var)) 
    { 
    } 
    else 
    { 
    } 
} 

然而,這不是面向對象的方式,也不是在variant-辦法。

更好的方法是使用的Boost.Variant全功率:

struct DoIt: boost::static_visitor<> 
{ 
    void operator()(const Animal& animal) const {} 
    void operator()(const Kid& kid) const {} 
}; 


int main(int argc, char* argv[]) 
{ 
    typedef boost::variant<Dog,Cat,Kid> variant_type; 

    variant_type var = /**/; 

    boost::apply_visitor(DoIt(), var); 
} 

注意如何static_visitor概念自然處理繼承。

+0

我認爲,訪問者可能並不適合這裏的確切目的,因爲我想處理任何變體 – Gokul 2010-04-22 04:47:35

+1

如果你看第一個解決方案,因爲唯一的'operator()'實現在訪問者是模板之一,它可以與任何變種:) – 2010-04-22 06:14:06