2011-01-16 49 views
15

繼續my journey into the world of variadic templates,我遇到了另一個問題。具有多個模板參數包的部分模板專業化

假設下面的模板類:

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

有可能部分專門它的可變參數模板實例是這樣的:

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

有了這個,foo<int>將對應於默認的實現和foo< std::tuple< int, char > >到專門的實施。

但是,使用多個模板參數時,事情會變得更加複雜。例如,如果我們有如下的模板類

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局部特殊化,我試圖定義一個成員函數,它都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 
    { 
    } 
}; 

在成員函數聲明,海灣合作委員會給我的錯誤

參數包必須是在參數列表的末尾。

據我所知,編譯器應該能夠爲給定的模板實例化定義正確的成員函數,例如, 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)的末尾 處出現。末端 注]

所以,正如你所說,函數參數包必須是最後一個參數 不幸。
類模板的非模板成員函數是該類在實例化(完全專用化)時的普通函數 。 所以我希望在這個問題中的代碼可以邏輯編譯,作爲 特殊情況。

+0

你是對的,代碼完美編譯!我添加的問題其實有點不同,我會編輯這個問題...抱歉給您帶來不便... –

+0

@LucTouraille:別擔心:-)這對我來說是一個很好的自我教育場合。 –

+0

有些東西讓我覺得這個報價並不打算在這裏適用,因爲這兩個參數包都是已知的,只是需要擴展。如果鏗鏘會接受此代碼,我不會感到驚訝 –