2017-07-16 80 views
3

我有一個類Foo需要有可變數量的模板參數,但這些參數需要是某種泛型類型,而不是完全任意的。例如變量模板部分特化類限制模板參數的類型

template < int I, typename T> struct Arg; 
using type1 = Foo<Arg<3, double>>; 
using type2 = Foo<Arg<1, int>, Arg<7, float>, Arg<1, int>>; 

我想知道什麼是最好的方式來實現這一點。我想我需要用一個簡單的可變參數模板第一次啓動

template < typename ...T > 
class Foo; 

從那裏,我可以按照遞歸路

template < int I, typename T, typename ...Others> 
template Foo<Arg<I, T>, Others...> 
{ 
    ... 
}; 

this answer另一個問題讀給我留下想知道我的知識可變參數模板以及如何遞歸有時可以避免。

我的問題是,這是否模板參數預計將在一個相對剛性的格式事實啓用Foo部分專業化這不會是遞歸的,這將有效地處理所有Foo S中的形式Foo<Arg<...>,Arg<...>,...>的?

回答

6

這工作:

#include <iostream> 

template <int i, typename T> struct Arg; 

template <typename ...T> 
class Foo; 

template <int ...Is, typename ...Ts> 
class Foo<Arg<Is, Ts>...> 
{ 
public: 
    static constexpr unsigned int N = sizeof...(Is); 
}; 

int main() 
{ 
    using type2 = Foo<Arg<1, int>, Arg<7, float>, Arg<1, int>>; 
    std::cout << type2::N << "\n"; 
} 

雖然它可能會或可能不容易或方便地使用模板參數以這樣的形式,這取決於你想與他們做什麼。

+0

人們仍然可以將參數放在一個元組中,並在需要時訪問它們,所以我不會說它們很難使用。簡單地添加N並輸入到'Arg'來輸出它們。 – skypjack

2

你可以用SFINAE做到這一點。這裏是一個草圖:

template<class...Bs> 
constexpr bool is_all_true(Bs...); // write this 

template<class T> 
constexpr bool is_valid_arg(); // write this 

template < class=void, class...Ts > 
class FooImpl; 

template <class...Ts> 
class FooImpl<std::enable_if_t<is_all_true(is_valid_arg<Ts>()...) >, Ts...> { 
    // code 
}; 

template<class...Ts> 
class Foo:FooImpl<void, Ts...> {}; 

現在FooFooImpl,測試,如果你的前提條件都得到滿足。

你必須寫is_all_trueis_valid_arg,其中is_valid_arg測試,如果T的形式Arg<int, Type>的。作爲一個例子,在C++ 17中,is_all_true只是return (true && ... && bs);(如果我沒有記錯的話,true是多餘的,但爲了清晰起見,我喜歡它)。在C++ 11/14中它會更難。

相關問題