[모던C++입문] 3.6 템플릿 특수화

    템플릿 특수화

    • 템플릿은 많은 인수타입에 대해 동일한 구현을 사용할수 있다.
    • 그러나 일부 타입에 대해서는 다른동작을 구현해야 할때도 있다.
    • 이를 위해 템플릿 특수화(Template Speicalization)을 사용하자.

    하나의 타입에 대한 특수화

    • 벡터 클래스에서 bool타입에 대해 특수화
    • bool값을 1바이트로 패킹하여 메모리 절약을 해보자.
    template <>
    class vector<bool> 
    {
      public:
        explicit vector(int size)
          : my_size(size), data(new unsigned char[(my_size+7) / 8])
        {}
    
        vector() : my_size(0) {}
    
        //상수 접근 연산자
        bool operator[](int i) const { return (data[i/8] >> i%8) & 1; }
    
        vector_bool_proxy operator[](int i) 
        { return {data[i/8], i%8};   }  //중괄호 리스트로 생성자 호출
    
      private:
        int                              my_size;
        std::unique_ptr<unsigned char[]> data;
    };
    
    class vector_bool_proxy
    {
      public:
        vector_bool_proxy(unsigned char& byte, int p) : byte(byte), mask(1 << p) {}
    
        operator bool() const { return byte & mask; }
    
        //대입 연산자
        vector_bool_proxy& operator=(bool b) 
        { 
        if (b)
            byte|= mask;
        else
            byte&= ~mask;
        return *this; 
        }
    
      private:
        unsigned char& byte;
        unsigned char  mask;
    };

    함수 특수화 및 오버로딩

    함수를 특정타입으로 특수화 하기

    • 함수 템플릿 특수화는 사용하지 말자.

    모호함

    template<typename Base, typename Exponent>
    Base inline power(const Base& x, const Exponent& y);
    
    template<typename Base>
    Base inline power(const Base& x, int y);
    
    template<typename Exponent>
    double inline power(double x, const Exponent& y);
    
    power(3.0, 2);  //세 오버로드가 모두 일치한다.
    
    //모호함을 없애기 위해선 다음 오버로드가 필요하다
    double inline power(double x, int y);

    부분 특수화

    //앞서 사용했던 템플릿 클래스인 vector와 complex 를 이용하여 다음과 같은 예제
    //> >사이에 공백을 두어야한다 붙이면 시프트 연산자로 해석
    template<typename Real>
    class vector<complex<Real> >  
    {...}
    
    //여러 매개 변수가 있는 클래스에도 사용 가능하다
    template<typename Value, typename Param>
    class vector<sparse_matrix<Value, Param> >
    {...}
    
    //포인터 또한 특수화가 가능
    template<typename T>
    class vector<T*>
    {...}

    부분 특수화한 함수

    • 함수 템플릿은 부분 특수화 할수 없지만 오버로드를 사용하여 비슷하게 사용가능
    template<typename T>
    inline T abs(const T&  x)
    {
        return x < T(0) ? -x : x;
    }
    
    template<typename T>
    inline T abs<const std::complex<T>& x)
    {
        return sqrt(real(x) * real(x) + imag(x) * imag(x));
    }
    반응형

    댓글

    Designed by JB FACTORY