在我的应用程序中,有一个继承层次结构,其中只有位于继承链末尾的类才是非抽象类。还有一些boost :: variant的用法。我想编写一个函数,它接受一个指针和一个Type,并说明该对象是否属于该类型。
例如
#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变量是否存储该特定类型。有人可以帮助我吗?我不想添加额外的参数来确定它是否是变体。即使找出抽象性,我也在使用boost :: is_abstract ..
谢谢, 戈库尔。
答案 0 :(得分: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) );
}
答案 1 :(得分: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
{
}
}
然而,这不是OO方式,也不是变种方式。
更好的想法是使用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
概念如何自然地处理继承。