2010-04-21 6 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.

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

그리고이 :

+0

dynamic_cast가 청구서를 작성하지 않습니까? –

+0

가능하면 동적 캐스트 대신에 typeid를 사용하고 싶습니다. Boost :: Variant가 동적 캐스팅과 작동하지 않습니다. – Gokul

답변

4

그럼이 두 가지 직접 가지 버전이 있습니다

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

나는 템플릿 깔끔하게 과부하에 그 처리 방법을 잘 모르겠습니다하지만 당신이 뭔가를 할 수 있습니다 : Boost.Variant 다루는

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

+0

오! 감사합니다. – Gokul

2

가장 깨끗한 방법은 사용하는 것이 일반적이다 방문자. 과 같이 사용할 수 있습니다

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-방법이 아니다, 어느 쪽도 아니 그것은 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; 
}; 

그럼 당신은 그것을 포장 할 수 있습니다 방법.

더 좋은 아이디어는 Boost.Variant의 모든 기능을 사용하는 것입니다 다음 static_visitor 개념을 자연스럽게 상속을 처리하는 방법을

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

참고.

+0

variant에서 type() 함수를 간과했습니다. 방문자가 어떤 변형을 다루려고하기 때문에 정확한 목적을 여기에 맞지 않을 수도 있습니다. – Gokul

+1

첫 번째 솔루션을 살펴보면 구현 된 유일한 연산자 인 operator 방문자가 템플릿 하나, 그것은 어떤 변형과도 작동합니다 :) –