2010-11-29 2 views
5

오래 전에 참조 정적 캐스트를 검사하지만, 형은 내가 수를 가정 것이 아니다 : 내가 원하는내가 static_cast를 수행 할 때마다 내가 어설를 얻을 수 있도록 나는 다음과 같은 템플릿을 생성 한

/// perform a static_cast asserted by a dynamic_cast 
template <class Type, class SourceType> 
Type static_cast_checked(SourceType item) 
{ 
    Assert(!item || dynamic_cast<Type>(item)); 
    return static_cast<Type>(item); 
} 

오늘

/// overload for reference 
template <class Type, class SourceType> 
Type &static_cast_checked(SourceType &item) 
{ 
    Assert(dynamic_cast<Type *>(&item)); 
    return static_cast<Type>(item); 
} 

그러나, 컴파일러는 내가 다른 참조에 대한 참조를 캐스팅하고 때이 오버로드를 사용하지 않는 것 :뿐만 아니라 포인터 만 참조하지 만 일하는 것이 변형을 만들 수 있습니다. 나는 이유를 이해하기에 충분하거나 템플릿이 작동하는 변형을 만들 수있을 정도로 템플릿 해상도 규칙을 이해하지 못한다.

참고 :이 프로젝트에서는 예외가 해제되어 있으므로 dynamic_cast<Type *>을 NULL로 확인하는 대신 bad_cast exception을 붙잡을 수 없습니다.

+1

당신은'SOURCETYPE의 *'에 대한 과부하를 추가하고 원래 은퇴 할 수 있습니까? 가치 유형을 전혀 지원해야합니까? (그리고 그 문제를 해결, 나는 지금 궁금해?) –

+1

나는이 코드 라인에 대해 생각하고, 왜 그것이 필요한지 이해할 수 없다. 동적 형변환을 사용하여 정적 형변환을 검사 할 경우 객체 만 검사 할 수있는 것보다 정적 형 형변환은 동적 형변환이 가능합니다. 저것은'dynamic_cast'의 재 구현입니다. 다이나믹 캐스트와 정적 캐스트의 차이점은 동적 캐스트가 vtable과 정적 캐스트를 조사하지 않는다는 것입니다. – nutario

+0

정적 캐스팅이지만 주장하는 유형입니다. 즉, 캐스팅하는 유형에 대한 가정이 잘못되었다고 디버그 시간을 알려줍니다. – Suma

답변

5

제거 *&는 :

Derived *d= static_cast_checked<Derived *>(b); 
Derived &d= static_cast_checked<Derived &>(b); 

편집 :

/// perform a static_cast asserted by a dynamic_cast 
template <class Type, class SourceType> 
Type static_cast_checked(SourceType *item) 
{ 
    Assert(!item || dynamic_cast<Type>(item)); 
    return static_cast<Type>(item); 
} 

template <class Type> struct make_pointer 
{ 
    typedef Type *PointerType; 
}; 

template <class Type> struct make_pointer<Type &> 
{ 
    typedef Type *PointerType; 
}; 

/// overload for reference 
template <class Type, class SourceType> 
Type static_cast_checked(SourceType &item) 
{ 
    Assert(dynamic_cast<typename make_pointer<Type>::PointerType>(&item)); 
    return static_cast<Type>(item); 
} 

는 그런 다음 원하는 구문을 사용할 수 있습니다 포인터 타입 변환을 추가했습니다.

+1

적어도 gcc를 사용하고 있다면 ('Assert (dynamic_cast (& item));) 참조에서 포인터 유형을 가져올 수 없습니다. 다른 컴파일러에 대해 잘 모르겠습니다. – nutario

+0

@nutario, 아, 네가 맞다. – MSN

+0

@nutario, fixed! – MSN

0

는 다음을 시도해보십시오

template<class Type, class SourceType> 
Type* static_cast_checked(SourceType* item) 
{ 
    // ... 
} 

template<class Type, class SourceType> 
Type& static_cast_checked(SourceType& item) 
{ 
    // ... 
} 

그런 다음 모든 포인터가 첫 번째 변종을 사용하고있는 모든 참조 부분 특수화 (IIRC)의 규칙에 두 번째를 사용합니다.

2

이 작동 :

/// perform a static_cast asserted by a dynamic_cast 
template <class Type, class SourceType> 
Type* static_cast_checked(SourceType *item) 
{ 
    Assert(!item || dynamic_cast<Type*>(item)); 
    return static_cast<Type*>(item); 
} 

/// overload for reference 
template <class Type, class SourceType> 
Type &static_cast_checked(SourceType &item) 
{ 
    Assert(dynamic_cast<Type *>(&item)); 
    return static_cast<Type&>(item); 
} 

이처럼 사용

Dervied d; 
Base* pbase = static_cast_checked<Base>(&d); 
Base& rbase = static_cast_checked<Base>(d); 

이 솔루션은 기능 템플릿을 오버로드에 의존합니다. 첫 번째 템플릿이 너무 일반적이기 때문에 솔루션이 작동하지 않았습니다. 이미 두 번째 기능이 포함되어 있습니다. 함수 템플릿은 전문화되어 있지 않습니다. 클래스 템플릿 만 특수화 할 수 있습니다. 반환 유형의

+0

위대한,이 쉽습니다 그리고 아주 잘 작동합니다. 가능한 경우 static_cast_checked 또는 static_cast_checked 을 쓸 수있는 솔루션을 선호합니다. 누구든지 어떤 것을 만들 수 있습니까?나는 이제 특수한 템플릿 클래스를 사용하여 힘든 일을하려고 노력 중이다. – Suma

+0

여러 가지 시도 (유형 특성 및 클래스 전문화 포함)를 시도했지만 컴파일 솔루션으로 오지 않았습니다. – WolfgangA

+0

과부하와 클래스 전문화의 조합으로 해결책을 찾은 것 같습니다. 내 새로운 대답을 확인해 주실 수 있으시겠습니까? – Suma

1
#include <boost/type_traits/add_pointer.hpp> 

template <class Type, class SourceType> 
Type static_cast_checked(SourceType *item) 
{ 
    assert(!item || dynamic_cast<Type>(item)); 
    return static_cast<Type>(item); 
} 

template <typename Type, class SourceType> 
Type static_cast_checked(SourceType &item) 
{ 
    typedef typename boost::add_pointer<Type>::type TypePtr; 
    assert(dynamic_cast<TypePtr>(&item)); 
    return static_cast<Type>(item); 
} 

이 구현은 STD-lib 디렉토리에서 static_cast 또는 dynamic_cast처럼 작동 :``

Base &b = static_cast_checked<Base&>(a); 
    Base* bPtr = static_cast_checked<Base*>(&a); 
+0

니스. 그것은 내 솔루션과 거의 같고 기술 배경도 동일하지만 부스트를 사용하면 조금 더 짧아 질 수 있습니다. – Suma

관련 문제