2017-02-17 1 views
2

나는 다음과 같은 클래스가 :나는 /이 템플릿 유형에 대한 템플릿 함수를 오버로드 전문 수있는 방법

template <> 
container<int>::container() { 
    std::cout << "int constructor" << std::endl; 
} 
:

template <class... T> 
class thing {}; 

template <class T> 
class container { 
    public: 
     container() { 
      std::cout << "normal constructor" << std::endl; 
     } 
}; 

내가 이런 식으로 container<int>의 생성자에 대한 전체 전문화를 쓸 수를

container<thing<T>>에 대해 비슷한 생성자를 정의하고 싶습니다. 나는 내가 무엇을 쓰기를 시도하고있어 템플릿 기능의 부분 특수화 생각 여기에 내가 시도하고있는 무슨이다 (불법입니다.) :

template <class T> 
container<thing<T>>::container() { 

} 

이 컴파일되지 않습니다.

이 문제를 해결하는 올바른 방법은 무엇인지, 템플릿 클래스 기능에 대한 과부하와 특수화 사이의 경계가 흐려지는 지 잘 모르겠습니다. 이 문제를 쉽게 해결할 수 있습니까? 아니면 type_traits (std::enable_if)가 필요합니까? 이 문제를 어떻게 해결할 수 있습니까? 당신은 부분적 할 수 없습니다

답변

7

를 전문으로 할 수 있지만이 부분은 전체 클래스를 전문으로 반드시 할 필요가 없습니다.

이렇게 해결할 수 있습니까? 아니면 type_traits/enable_if가 필요합니까? 이 문제를 어떻게 해결할 수 있습니까?

생성자 및 태그 디스 패칭을 위임하면 제한 사항을 해결할 수 있습니다.

#include<iostream> 

template <class... T> 
class thing {}; 

template <class T> 
class container { 
    template<typename> 
    struct tag {}; 

    template<typename U> 
    container(int, tag<thing<U>>) { 
     std::cout << "thing<U>" << std::endl; 
    } 

    container(char, tag<T>) { 
     std::cout << "normal constructor" << std::endl; 
    } 

public: 
    container(): container(0, tag<T>{}) {} 
}; 

int main() { 
    container<int> c1; 
    container<thing<int>> c2{}; 
} 

wandbox에 그것을 참조 :
그것은 최소한의 근로 예를 들어 다음과 같습니다.


올바른 위임자를 선택하는 위임자 생성자가 두 명 이상인 경우 쉽게 확장 할 수 있습니다. 예를 들어
는 :

#include<iostream> 

template <class... T> 
class thing {}; 

template<typename> struct tag {}; 
template<int N> struct prio: prio<N-1> {}; 
template<> struct prio<0> {}; 

template <class T> 
class container {  
    template<typename U> 
    container(prio<2>, tag<thing<U>>) { 
     std::cout << "thing<U>" << std::endl; 
    } 

    container(prio<1>, tag<double>) { 
     std::cout << "double" << std::endl; 
    } 

    container(prio<0>, tag<T>) { 
     std::cout << "normal constructor" << std::endl; 
    } 

public: 
    container(): container(prio<2>{}, tag<T>{}) {} 
}; 

int main() { 
    container<int> c1; 
    container<double> c2; 
    container<thing<int>> c3{}; 
} 

wandbox에를 참조하십시오.

+1

매우 세련된 솔루션 (IMHO) – max66

+0

@ max66 감사합니다. 전체 클래스를 부분적으로 특수화하면 코드 중복이 발생할 수 있으므로 가능한 한 피하려고합니다. – skypjack

+0

@ max66 _specialized_ 생성자가 여러 개인 경우에 대한 자세한 정보가 추가되었습니다. 네가 그걸 좋아하기를 바란다. ;-) – skypjack

4

생성자를 전문으로하지만 당신은 부분 생성자를 전문으로 당신은 부분적으로 할 수없는 전체 클래스

template <class T> 
class container<thing<T>> 
{ 
    public: 
     container() { } 
}; 
+0

이렇게하면 완전히 (다시) 클래스를 정의해야합니다. – user2079802

+0

@ user2079802 - 예; 그러나, 당신이 (재) 정의해야하는 클래스의 부분이 전체 클래스에 비해 작다면, 당신은 정의/재정의 할 부분 만 가진 작은 기본 클래스를 생성 할 수 있습니다. – max66

+0

@ user2079802 - 또한 skypjack의 솔루션을 살펴 보자 : 부분적으로 생성자를 전문화하지 말고, 태그 파견과 생성자 위임을 결합하여 전체 클래스를 재정의하지 않고도 문제를 해결할 수있다. – max66