2013-05-03 1 views
0

정수 값을 래핑하고이 값이 항상 유효한 범위 내에 있는지 확인하기 위해 C++ 템플릿 클래스를 만들려고합니다. 따라서 간단한 코드는 다음과 같습니다.다른 템플릿 매개 변수를 사용하여 C++ 템플릿간에 암시 적으로 캐스트하는 방법

struct OutOfRangeError 
{ }; 

template<int MIN, int MAX, typename TYPE> 
struct IntegerRange 
{ 
    private: 
    TYPE mValue; 

    public: 
    IntegerRange(const TYPE value) : mValue(value) 
    { 
     if (MIN > value || value > MAX) 
     { 
      throw OutOfRangeError(); 
     } 
    } 

    operator TYPE() const 
    { 
     return mValue; 
    } 
} 

이전 코드는 작동하지만이 클래스를 사용하면 약간의 단점이 있습니다. 다음은 샘플입니다

typedef IntegerRange<0, 4, int> range1_t; 
typedef IntegerRange<0, 5, int> range2_t; 

range1_t a = 3; 
//range2_t b = a; // This does not work 
range2_t b = static_cast<int>(a); // This works OK 

그래서, 내가 명시 적으로 주어진 형식으로 캐스팅 할 다른 범위 사이의 값을 할당 할 수 있습니다. 나는이 명시적인 캐스트를 피하고 IntegerRange 클래스를 다루는 해결책을 일반 정수처럼 사용하고 싶습니다. 따라서 개발자는 클래스 대신 일반 정수를 처리하고 있다는 느낌을 가져야합니다.

이 문제를 해결하기 위해 여러 가지를 시도했습니다. 이 RANGE_TYPE이 형식으로 캐스팅 할 수있는 유형이 될 수 있습니다 나는 너무 많이 좋아하지 않아, 작동하고, 나는이를 제한하고자하는 경우에도, 그러나

template<typename RANGE_TYPE> 
IntegerRange(const RANGE_TYPE &value) : 
     mValue(static_cast<const TYPE>(value)) 
{ 
    if (MIN > mValue || mValue > MAX) 
    { 
     throw OutOfRangeError(); 
    } 
} 

: 하나의 작업은 생성자에 추가로 다음 하나입니다 IntegerRange 클래스에만 적용됩니다.

template<int ARG_MIN, int ARG_MAX, typename ARG_TYPE> 
IntegerRange(const IntegerRange<ARG_MIN, ARG_MAX, typename ARG_TYPE> &value) : 
     mValue(static_cast<const TYPE>(value)) 
{ 
    if (MIN > value || value > MAX) 
    { 
     throw OutOfRangeError(); 
    } 
} 

질문 2입니다 :
* 왜 코드의 마지막 조각을 컴파일하고 무엇을하지 않은 경우에만 IntegerRange 클래스로 제한하려면 나는 다음하지만 컴파일되지 않고 나는 이유를 이해하지 못하는 시도 컴파일하기 위해 변경해야합니다.
* 내가 누락 된 명시 적 캐스트를 피하는 것이 더 좋습니까?

감사가 이미 POSIX 숫자 상수로 정의 될 수 있기 때문에 템플릿 이름으로 ARG_MAX을 사용해서는 안

+0

무엇이 오류 메시지입니까? –

+0

오류 메시지 : 오류 : 'range1_t {aka IntegerRange <0, 4, int>}'에서 gcc의 비 스칼라 유형 'range2_t {aka IntegerRange <0, 5, int>}'로 변환되었습니다. –

+0

전체 코드를 그대로 게시 할 수 있습니까? 나는 그것이 효과가 있어야한다고 생각한다. –

답변

2

첫째,. 또한 어쩌면 당신이 직접 operator ARG_TYPE()를 호출하는 ARG_TYPEvalue 캐스팅해야

IntegerRange(const IntegerRange<ARG_MIN, ARG_MAX, ARG_TYPE> &value) : 

을 다음 컴파일러가 ARG_TYPE에서 TYPE로 변환하자

둘째, 당신은 IntegerRange의 세 번째 템플릿 인수에 typename을 제거해야합니다 TYPE으로 캐스팅하는 대신 컴파일러에서 가능한 변환을 ARG_TYPE에서 호출하고 operator ARG_TYPE()에서 호출하도록합니다. 첫 번째 솔루션을 사용하면 불가능한 변환에 대한 컴파일 오류가 더 명확해질 수 있습니다.

+0

TYPE 대신 ARG_TYPE 전송에 대한 의견이있을 수 있습니다. 그러나 아직도 컴파일 중이 지 않으며 더 많은 오류가 나타나고 있다고 말하는 것은 후회합니다. ../lib/src/IntegerRanges.hpp:153:31 : 오류 : 숫자 상수 앞에 '>'가 나타날 것임 ../lib/src/IntegerRanges.hpp:154:67 : 오류 : 'ARG_TYPE'이 (가) 선언되지 않았습니다. 범위 ../lib/src/IntegerRanges.hpp:154:75 : 오류 : 템플릿 인수 3이 잘못되었습니다 – Charlie

+0

어떤 컴파일러를 사용하고 있습니까? 그것은 GCC 4.7에서 잘 컴파일됩니다. – zakinster

+1

@Charlie'ARG_MAX'가 숫자 상수이기 때문에 리눅스에서 같은 오류가 발생합니다. 템플릿 매개 변수의 이름을 바꾸면됩니다. – zakinster

0

RANGE_TYPE can be any type able to cast to TYPE, and I would like to restrict this to only IntegerRange classes. To restrict it only to IntegerRange

그냥 템플릿 인수의 순서를 교환하고 템플릿 인수 공제가 암시 적으로 인수 형식을 변환하지 않기 때문에이 작동합니다

template<typename TYPE, TYPE2 MIN, TYPE2 MAX> 
struct IntegerRange 

로 선언합니다. 예를 들어 int에서 float.
물론
//range2_t b = a; // This does not work 

. ab에는 다른 유형이 있습니다. 각 템플릿 전문 분야에 대해 클래스의 새 템플릿이 만들어 졌는지 기억하십시오. 유형이 유사하기 때문에 두 개의 객체를 지정할 수 없습니다. 다른 IntegerRange에서 IntegerRange을 구성 할 수 있습니다 복사 생성자를 제공 할 필요가 a = b 위해

class A { int a; }; class B { int a; }; 
A a; B b; a = b; // Should not work 

가해야 할 일. (타입 변환 연산자가 있기 때문에 여기에 할당 할 필요가 없습니다.)

template<typename TYPE2, TYPE MIN2, TYPE MAX2> 
IntegerRange(const IntegerRange<TYPE2,MIN2,MAX2>& ot) { 
    if (MIN > ot.mValue || ot.mValue > MAX) 
    { 
     throw OutOfRangeError(); 
    } 

    mValue = ot.mValue; 
} 
+0

사실,'range2_t b = a;'를 실행함으로써, 컴파일러가'a'의'연산자 int()'와'b'의 생성자'IntegerRange (const int)'를 호출 할 것으로 기대했다고 생각합니다. 물론 C++ 컴파일러는 그렇게까지 추론하도록 설계되지 않았습니다. – zakinster

관련 문제