2013-06-21 3 views
2

: 나는 가상 템플릿을 사용할 수 없습니다 알고템플릿 클래스를 변환하는 방법? 내가 예를 들어 다음과 같은 한

Wrapper *t = new WrapperT<int>(1); 
WrapperT<double> *t2 = t->clone<double>(); 

:

struct Wrapper 
{ 
    virtual ~Wrapper() 
    { 
    } 

    template <typename U> 
    WrapperT<U> * clone() 
    { 
     return new WrapperT<U>(value); //will not work, because value is not known here 
    } 
}; 

template <typename T> 
struct WrapperT : Wrapper 
{ 
    explicit WrapperT(T v) 
    { 
     value = v; 
    } 

    T value; 
}; 

나는 이런 식으로 뭔가를 할 수 있습니다. 어떤 아이디어?

+0

다른 사람이 다음 줄에 't-> 복제 ()'을 (를) 만들 때 어떤 일이 일어나기를 원하십니까? ('foo'는 완전히 관련이없는 타입입니다.) – Yakk

+1

변환 구성 자'템플릿은 무엇인가요? explicit WrapperT (const WrapperT &);'? – jrok

+0

@jrok : 그 생성자는 실제 타입을 알지 못할 것입니다. 그는 포인터를 기초에서 파생 된 유형으로 변환하려고합니다. –

답변

0

가능한 접근 방식은 방문자 패턴을 정의하는 것입니다. 그러나 여러 가지 래핑 된 유형 (예 : 작은 하위 집합이 아닌 경우)을 지원하려면 방문자 구현 비용이 커질 수 있습니다.

당신이 얻을 수있는 또 다른 문제는 변환이 동적으로 전달되기 때문에 런타임에 실패 할 수 있으며이를 감지하고 그에 따라 행동하는 메커니즘을 제공해야한다는 것입니다 (예외가 떠오른다) . 끔찍한 건 ...

+0

이 패턴은 내 앱에 적합하지 않습니다. 컴파일러에서 지원하는 가능한 모든 유형을 변환하고 싶습니다. –

+0

@SteffenRoeber : 전달하는 요소가 기본 유형 일 때 유형 정보가 손실되는 것이 문제입니다. 해당 유형 정보를 복구하려면 런타임시 동적 디스패치를 ​​사용해야하지만 전체 * generic * 솔루션을 사용하려면 템플릿과 정적 디스패치가 필요합니다. 즉, 컴파일러에서 필요한 코드를 생성하도록합니다. 다른 디자인을 찾아야합니다. –

0

내가 제안하는 해결책은 동적으로 (David Rodriguez - dribeas가 지적한대로) 유형 변환을하는 "중립 유형"을 사용하는 것입니다.

장점 :이 솔루션은 일반적인입니다

  • : 새로운 유형을 사용할 때 당신이 그렇게 특별한 것은 필요하지 않습니다.

으로는 성능을

  • 안 좋은 단점.
  • 삽입 및 추출 스트림 연산자를 정의해야합니다.

코드 :

struct Wrapper 
{ 
    // get the "neutral type" value 
    virtual string getValue() const = 0; 

    template <typename U> Wrapper* clone() const; 
}; 

template <typename T> 
struct WrapperT: Wrapper 
{ 
    explicit WrapperT(T v): value(v) 
    { 
    } 

    virtual string getValue() const 
    { 
     // use streams to conversion to neutral value, but 
     // other better method would be suitable 
     ostringstream strm; 
     strm << value; 
     return strm.str(); 
    } 

    T value; 
}; 

template <typename U> Wrapper* Wrapper::clone() const { 
    U value; 
    istringstream strm(getValue()); 
    strm >> value; 

    return new WrapperT<U>(value); 
} 

편집 : 숫자 만 유형을 사용하는 경우 더 나은 성능의 솔루션을

, 우리는 "중립 형 '으로 long double에 의해 string을 변경할 수 있습니다

template <typename T> 
double long WrapperT<T>::getValue() const 
{ 
    return value; 
} 

template <typename U> Wrapper* Wrapper::clone() const { 
    return new WrapperT<U>(getValue()); 
} 

플로팅에 대해 정수형 만 사용할 때 점 변환? 그 경우, 용액은 약간 더 복잡해질 것이다

  • U 템플릿에 따라 선택 clone() 기능에서 원하는 getValue() 함수를 두 getValue() 가상 함수 부동 소수점 대 정수 다른 하나씩,
  • 을 만들 매개 변수 유형 (대상 유형).
+0

고성능 솔루션이 필요합니다. 스트리밍은 선택의 여지가 없습니다. –

+0

트램펄린 기능에 대해 읽었습니다. 그러나 그들이 여기에 적당하다면 나는 모른다. –

+0

@SteffenRoeber : 자신 만의 변환 함수를 만들 수 있습니다. 항상 숫자 형을 사용한다면 중립 타입으로 부동 소수 형 (double 또는 long double)으로 변환 할 수 있습니다. – Gonmator

관련 문제