2014-03-26 171 views
2

我想定義一個類,它接受一個非類型參數列表,可能包含不同類型的參數。例如,下面應該是有效的:C++ variadic模板,具有不同類型的非類型參數

Test<3, 4.5, 6> t; 

如果所有參數具有相同的類型,說int,我可以用如下的定義:

template<int... args> 
class Test { 
    // ... 
}; 

更具體地講,在我的具體使用如果有第二類Base與多個成員,並且我想通過Base成員指針。

Test<&Base::a, &Base::b> 

如果Base::aBase::b有一個共同的類型T,那麼我可以定義Test如下。

template<int Base::* ...args> 
class Test { 
    // 
}; 

我該怎麼去定義這樣的類Test

+0

那麼究竟是什麼問題? – iavr

+3

我認爲你可以得到的最好的東西是使用'std :: integral_constant'或類似的東西,並使用一組類型的模板參數。然後可以使用宏來減少鍋爐位置,例如:#define C_MEM_FUN(X)std :: integral_constant '然後'Test ' – dyp

+1

我認爲'template '應該是'template '。 – Constructor

回答

5

你可以做到這一點通過以下方式:

template <class... Types> 
struct Wrapper 
{ 
    template <Types... args> 
    class Test { 
     // ... 
    }; 
}; 

注意,簡單的符號template <class... Types, Types... args> class Test;不被許可的標準(見第[temp.param] 14.1/15)。

使用(注意 floatdoublelong double常數不能非類型模板參數)的

實施例:

Wrapper<int, char, unsigned>::Test<1, '2', 3U> t; 

與成員指針更具體的情況下,可以類似地實施:

struct Base 
{ 
    int a; 
    float b; 
    void c() {} 
}; 

template <class... Types> 
struct Wrapper 
{ 
    template <Types Base::*... args> 
    class Test { 
     // 
    }; 
}; 

使用示例:

Wrapper<int, float, void()>::Test<&Base::a, &Base::b, &Base::c> t2; 

使用可變參數宏和decltype關鍵字可以縮短此表示法。

+0

你可否詳細說一下你有關'decltype''的評論?如果我可以在'''Wrapper'''後面刪除類型列表,這將是理想的,因爲它們是多餘的。 –

+0

我知道的最簡單的方式是'std :: make_tuple'的風格 - 用參數相關的查找推導出類型。據說,我讀到'make_tuple'對這個世界可能不是很長,這與C++慣例是相反的。你會期望'template X(T && ...)'的構造函數參數推導出'X ',但是ADL必須從它自己的構造函數中查找一個類型,在類型實例化之前ctor存在。你需要一個通用的選擇和/或一種方式來指定構造函數來推斷 - 所有這些都可能在工作中。 –

+0

個人而言,我想'friend'構造函數是語法。我試着建立一個「朋友」工廠,但當我意識到我的實現朝着使用std :: integral_constant的方向前進時,我停下了腳步,並且如果std庫作者使用了他們所做的模板簽名,那麼它可能是棘手的。 –