2010-04-21 4 views
0

Dans mon application, il existe une hiérarchie d'héritage dans laquelle seules les classes situées à la fin de la chaîne d'héritage sont des classes non abstraites. Il y a aussi une utilisation de boost :: variant. Je veux écrire une fonction qui prend un pointeur et un type et indique si l'objet appartient à ce type.identification du type

Par exemple

#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); 
} 

Maintenant, s'il y a une variante de boost, je veux savoir si les magasins de variantes de stimuler ce type particulier. Quelqu'un peut-il m'aider avec ça? Je ne veux pas ajouter un paramètre supplémentaire pour savoir s'il s'agit d'une variante. Même pour trouver l'abstrait, j'utilise boost :: is_abstract ..

Merci, Gokul.

+0

Est-ce que dynamic_cast ne remplit pas la note pour vous? –

+0

Nous voulons utiliser typeid à la place de la distribution dynamique autant que possible. Boost :: Variant ne fonctionne pas avec la distribution dynamique – Gokul

Répondre

4

Eh bien, il y a deux versions directes de cette:

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

Et ceci:

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

Je ne sais pas comment gérer cela avec votre modèle de surcharge proprement mais vous pouvez faire quelque chose comme ça :

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

Je veux le faire sans ajouter un paramètre de modèle pour dire si c'est une variante ... – Gokul

+0

oh! j'ai négligé la fonction type() en variante merci – Gokul

2

Le moyen le plus propre de traiter Boost.Variant est normalement d'utiliser un visiteur.

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; 
}; 

Ensuite, vous pouvez envelopper:

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

qui peut être utilisé comme ceci:

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

    variant_type var = /**/; 

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

Toutefois, ce n'est pas le OO-chemin, et ni ce sont les variant- façon.

Une meilleure idée serait d'utiliser la pleine puissance de 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); 
} 

Notez comment le concept static_visitor gère naturellement l'héritage.

+0

Je pense, visiteur ne peut pas répondre à l'objectif exact ici, comme je veux traiter avec une variante – Gokul

+1

Si vous regardez la première solution, puisque le seul 'opérateur()' mis en œuvre dans le visiteur est un modèle, ça marchera avec n'importe quelle variante :) –

Questions connexes