определение типа - PullRequest
       9

определение типа

0 голосов
/ 21 апреля 2010

В моем приложении есть иерархия наследования, в которой только классы в конце цепочки наследования являются неабстрактными классами. Также есть некоторое использование boost :: варианта. Я хочу написать функцию, которая принимает указатель и тип и говорит, принадлежит ли объект этому типу.

Например

#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.

Ответы [ 2 ]

4 голосов
/ 21 апреля 2010

Ну, есть две прямые версии этого:

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) );
}
2 голосов
/ 21 апреля 2010

Самый простой способ иметь дело с Boost.Variant - это обычно использовать Visitor.

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 естественным образом обрабатывает наследование.

...