2010-06-24 3 views
1

C++ 템플릿을 사용하여 간단한 정수 범위 검사기 및 변환기를 만들고 싶습니다.
코드는 다음과 같습니다C++에서 안전한 정수 변환

// D is the "destination" type and S the "source" type 
template <class D, class S> 
inline D SafeConvert(S value); 

template <class S> 
inline int SafeConvert<int>(S value) { 

    ASSERT(value >= S(INT_MIN) && value <= S(INT_MAX)); 
    return int(value); 
} /// error C2768: 'SafeConvert' : illegal use of explicit template arguments 


template <class S> 
inline size_t SafeConvert<size_t>(S value) { 

    ASSERT(value >= S(0) && value <= S(size_t(-1))); 
    return size_t(value); 
} /// error C2768: 'SafeConvert' : illegal use of explicit template arguments 


// ... 

void test() { 

    size_t v = INT_MAX+1; 
    int iv = SafeConvert<int>(v); 
} 

그러나 나는이 다음과 같은 와서 컴파일 오류 :

error C2768: 'SafeConvert' : illegal use of explicit template arguments 

내 질문은 어떻게에만 D 클래스를 전문으로하고자하는 컴파일러에게하는 것입니다?

감사합니다.

+0

시도해 볼 수 있습니다. http://stackoverflow.com/questions/998571/c-template-for-safe-integer-casts/998982#998982 –

답변

5

당신은 부분적으로 기능 템플릿을 전문으로 할 수없는 다음과 같이

후자는 구현 될 수있다. 클래스 래퍼로 흉내 내거나 표준 함수 오버로딩을 사용해야합니다. mimicing의 예 :

template <typename T1, typename T2> 
struct processor; 

template < typename T1, typename T2 > 
T1 fun(T2 t2) { return processor<T1,T2>::apply(t2); } 

template < typename T2 > 
struct processor<int,T2> 
{ 
    static int apply(T2 t2) { .... } 
}; 

...etc... 
+0

또는 라이브러리를 사용하십시오. –

1

SafeConvert에 의해 사용되는 SafeConverter<T, S> 구조체를 작성하십시오. 부분 전문화보다 더 나은 것은 std::numeric_limits 또는 심지어 boost::numeric_cast을 사용하는 것입니다. 이미 더 정교한 방식으로 범위 검사를 구현합니다.

template<typename T, typename S> 
struct numeric_converter { 
    static T convert(const S& val); 
} 
template<typename T, typename S> 
T numeric_cast(const S& val) { 
    typedef numeric_converter<T, S> converter; 
    return converter::convert(val); 
} 
+1

거의 같은 말을했지만, 먼저 대답을 확인 했어야합니다. 그렇다면 왜 그렇게 할 수 없는지 기억했을 것입니다. –

+0

그래서 문제는 답변이 너무 빨리 팝업되어 게시하기 전에 대개 내 대답을 생각할 시간이 없다는 것입니다. – Philipp

0

그냥, 생각, SafeConvert<size_t, S> 대신 SafeConvert<size_t> 쓰기에만 두 번째 매개 변수를 전문으로합니다. 노아 로버츠 (Noah Roberts)도 함수 대 유형의 부분 전문화의 관점에서 정확하다.

+0

다른 방법 라운드; 첫 번째 (대상) 인수를 특수화하려고합니다. –

+0

@ 마이크 : 고마워요. –

4

유지 보수가 어려울 것입니다.

일반적으로 내가 사용하는 조언을 것 numeric_limits :

template <class D, class S> 
D SafeConvert(S value) 
{ 
    ASSERT(value >= std::numeric_limits<D>::min() 
     && value <= std::numeric_limits<D>::max()); 
    return static_cast<D>(value); 
} 

그러나 당신이 부호 하나에 정수를 비교 할 때마다 컴파일러에 의해 방출 경고가 ... (정말 방법으로이 문제를 이해하지)가

휠 재발견 대신 Boost.NumericConversion 및 특히 boost::numeric_cast<>의 사용을 권장합니다.

검사가 필요하지 않을 때 (예 : 대상 유형이 소스 유형보다 크면) 성능이 보장되고 필요한 경우 검사를 수행해야합니다.

+0

숫자 제한과 boost :: numeric_cast가 최선의 방법입니다. – Puppy

+0

그것은 S의 최대 값이 더 크고 D의 최대 값이 더 큰 상황에서 모두 작동합니까? 아니면 암시 적 변환이 한 방향으로 그것을 망칠 것입니까? –

+0

@JosephGarvin :'boost :: numeric_cast'가 작동한다고 확신합니다.) 여기에 제시된 사용자 정의 솔루션의 경우 암시 적 변환을 마음에 두지 않을까 걱정됩니다. –