2010년 7월 8일 목요일

템플릿 프로그래밍에서 복소수를 실수 또는 복소수형 변수에 대입

템플릿으로 생성한 클래스에 적합한 변수형을 인자로 받아서 내부에 저장된 복소수 값을 이용하여 인자를 변경하는 상황을 가정해보자. 아래의 ClassA 클래스에 있는 update 메서드는 객체에 적합한 변수형을 인자로 받지만, 내부 계산은 복소수로 처리한다.
#include 

template 
class ClassA
{
public:
    ClassA(): cmplx(0,0) {}
    void update(T& out) { out = cmplx; }
private:
    std::complex cmplx;
};
문제는 복소수를 인자에 대입하는 부분에서 발생한다. out이 복소수형일 때엔 문제가 안 되지만, float이나 double과 같은 실수형이라면 형변환 에러가 발생한다. STLstd::complex 타입은 실수형으로의 변환 연산을 제공하지 않기 때문이다. 즉, std::comlex<double> 형으로 생성한 ClassA는 별문제가 없지만,
ClassA<std::complex<double> > obj;
std::complex<double> var;

obj.update(var);
double 형으로 생성한 ClassA
ClassA obj;
double var;

obj.update(var);
컴파일하면, 다음과 같은 에러가 발생한다.

error: cannot convert ‘std::complex<double>’ to ‘double’ in assignment

이 문제는 복소수형 변수를 실수형 변수로 변환해주는 함수를 만들어 해결한다. ClassA::cmplx의  실수부에 원하는 값이 저장되어 있다고 한다면, std::complex.real()의 반환값을 실수형 변수에 대입하면 된다.
template <typename S, typename T>
static inline T& assign(const std::complex<S>& in, T& out)
{
    return out = static_cast<T>(in.real());
}
하지만 이 함수를 사용하면, 오히려 복소수형 변수를 복소수형 변수에 대입하는 경우가 문제가 된다. 따라서 복소수형에 대해서는 다음과 같이 부분 템플릿 특수화(partial template specialization)를 이용하여 실수부와 허수부끼리 대입해주어야 한다.
template <typename S, typename T>
static inline std::complex<T>& assign(const 
std::complex<S>& in, std::complex<T>& out)
{
    out.real(static_cast<T>(in.real()));
    out.imag(static_cast<T>(in.imag()));
return out;
}
이제 update 함수는 아래와 같이 바꾸면 형변환 문제가 해결된다.
...
    void update(T& out) { assign(cmplx, out); }
...

댓글 없음:

댓글 쓰기