2011-01-16 6 views
15

계속 my journey into the world of variadic templates, 다른 문제가 발생했습니다. foo<int>는 기본 구현 및 foo< std::tuple< int, char > >에 해당되며,이와여러 템플릿 매개 변수 팩을 사용하여 부분 템플릿 전문화

template < template < typename ... > class T, typename ...Args > 
struct foo< T<Args...> > 
{ 
    //specialized implementation 
}; 

:

template < typename T > 
struct foo 
{ 
    //default implementation 
}; 

이 부분적으로 가변 인자 템플릿이 같은 인스턴스 생성을 위해 전문 수 있습니다 :

다음 템플릿 클래스를 가정 전문화 된 구현으로

그러나 여러 가지 템플릿 매개 변수를 사용하면 상황이 더욱 복잡해집니다. 우리는 다음과 같은 템플릿 클래스

template < typename T, typename U > 
struct bar {}; 

을 가지고 있고 우리는 우리가 foo 위해했던 것처럼 부분적으로 전문하려는 경우 예를 들어, 우리는 내가 올바른 오전, 우리는 할 수있다, 실제로

template < template < typename ... > class T, typename ...TArgs, 
      template < typename ... > class U, typename ...UArgs > 
struct bar< T<TArgs...>, U<UArgs...> > {}; 

//This would correspond to the specialized version with 
//T=std::tuple, 
//TArgs=int,char 
//U=std::tuple, 
//UArgs=float 
bar< std::tuple< int, char >, std::tuple<float> > b; 

할 수 없습니다 하나의 템플리트 매개 변수 팩을 가지며 매개 변수 목록의 끝에 위치해야합니다. 나는 이것이 템플릿 선언에서 필수적인 이유를 이해하지만 위의 예제와 같은 특정 부분 템플릿 전문화에 대해서는 이것이 문제가되지 않아야한다.

여러 템플릿 매개 변수 팩을 사용하여 부분 템플릿 전문화를 수행 할 수 있습니까?


편집이 : 지금은 바보 느낌 ... 내가 위에서 준 코드는 (적어도 GCC 4.5) 완벽하게 컴파일합니다. 내가 가진 컴파일 오류는 다중 매개 변수 팩 때문이 아니라 멤버 함수 매개 변수로 사용되기 때문입니다. bar의 부분 특수화에서, I는 모두 TArgsUArgs 파라미터 얻어 멤버 함수를 정의하려고 : 멤버 함수 선언에서

template < template < typename ... > class T, typename ...TArgs, 
      template < typename ... > class U, typename ...UArgs > 
struct bar< T<TArgs...>, U<UArgs...> > 
{ 
    void method(TArgs... targs, UArgs... uargs) //compile error here 
    { 
    } 
}; 

를 GCC 내게 오류

제공

파라미터 팩 있어야 매개 변수 목록 끝에.

내가 알 수있는 한 컴파일러는 주어진 템플릿 인스턴스화에 대한 올바른 멤버 함수를 정의 할 수 있어야합니다. bar< std::tuple< int, char >, std::tuple<float> >에는 멤버 함수 void method(int, char, float)이 포함되어야합니다. 내가 뭔가 잘못하고 있는거야? 아니면 불가능한 일을하려고합니까? 그렇다면 이것이 불가능한 이유가 있습니까?

+0

깔끔하고, 템플릿 목록의 요소를 템플릿 자체로 지정하거나 지정할 수 있다는 것을 알지 못했습니다. – JAB

답변

6

아마도이 답변을 통해 직접 질문을 해결할 수는 없지만 코드를 테스트했지만 다음 코드는 ideone (gcc-4.5.1)에서 컴파일되었습니다.

#include <cstdio> 
#include <tuple> 

template< class, class > struct S { 
    S() { puts("primary"); } 
}; 

template< 
    template<class...> class T, class...TArgs 
, template<class...> class U, class...UArgs 
> 
struct S< T<TArgs...>, U<UArgs...> > { 
    S() { puts("specialized"); } 
}; 

int main() 
{ 
    S< int, int > p;          // "primary" 
    S< std::tuple< int, char >, std::tuple<float> > s; // "specialised" 
} 
이 코드가 엄격하게 준수 모르겠어요

하지만 까지 내가 N3225 14.5.3을 읽을 때, 나는 템플릿 매개 변수 팩이 마지막 템플릿으로 가지고 을 언급 문을 찾을 수 없습니다 매개 변수.

편집 :
내가 N3225을 다시 읽고있는 다음 문 :

8.3.5/4 매개 변수 선언 절 은 생략 또는 함수 매개 변수 팩 종료되면 (14.5.3) 인수가 이면 과 같거나 기본값이 이 아니며 매개 변수 팩이 아닌 매개 변수의 수보다 커야합니다.

14.8.2.5/10 [참고 : 함수 매개 변수 팩은 매개 변수 선언 목록 (8.3.5)의 끝에 만 발생할 수 있습니다. 당신이 언급 한 바와 같이 -end 노트]

따라서, 함수 매개 변수 팩은 마지막 매개 변수 불행하게도이어야한다.
클래스 템플릿의 비 템플릿 멤버 함수는 인스턴스화 (완전히 특수화) 될 때 해당 클래스의 일반 함수 입니다. 이 질문에있는 코드를 특별한 경우로 논리적으로 컴파일 할 수 있기를 바랍니다.

+0

맞습니다. 코드가 완벽하게 컴파일됩니다! 내가 추가하는 이슈는 실제로 조금 다릅니다. 나는 질문을 편집 할 것입니다 ... 불편을 끼쳐 드려 죄송합니다 ... –

+0

@ 루크 트라 일레 : 걱정 마세요 :-) 이것은 나에게 좋은 교육적 행사였습니다. –

+0

무언가가 나를 만듭니다. 두 매개 변수 팩이 이미 알려져 있고 확장 만하면되므로 견적을 여기에 적용하지 않으십시오. clang이이 코드를 받아들이면 놀라지 않을 것입니다 –