2017-09-24 37 views
3

我會盡量簡單解釋我目前的問題。它可以很容易地解決,但我迄今發現的唯一解決方案並不能滿足自己,也許你會向我表明解決方案需要的下一級間接性。C++模板聲明限制專業化太多

我在這裏使用CRTP,即使這不是問題的關鍵。下面是一段代碼,重現我的問題:

template <typename T> 
class A 
{ 
    public: 
     static void p() 
     { 
      T::p(); 
     } 
}; 

template <typename T> 
class B 
{ 
    public: 
     static void q() 
     { 
      T::q(); 
     } 
}; 



????? template <??????> ???? // How to declare C here ??? 
class C; 


//now first specializations with A 
template <int a> 
class C<a> : public A<C<a> > 
{ 
    public: 
     static void p() 
     { 
      //specific stuff 
     } 
}; 

template <int a, typename Other_handlers ...> 
class C<a, Other_handlers...> : public A<C<a, Other_handlers...> > 
{ 
    public: 
     static void p() 
     { 
      //specific stuff 
     } 
}; 

template <int a, typename Child> 
class C<a, B<Child> > : public A<C<a, B<Child> > > 
{ 
    public: 
     static void p() 
     { 
      //specific stuff 
     } 
}; 



//second specializations with B 
template <int a, int b> 
class C<a, b> : public B<C<a, b> >, C<a> 
{ 
    public: 
     static void q() 
     { 
      //specific stuff 
     } 
}; 

template <int a, int b, typename Other_handlers ...> 
class C<a, b, Other_handlers...> : public B<C<a, b, Other_handlers...> >, C<a> 
{ 
    public: 
     static void q() 
     { 
      //specific stuff 
     } 
}; 

template <int a, int b, typename Child> 
class C<a, b, B<Child> > : public B<C<a, b, B<Child> > >, C<a> 
{ 
    public: 
     static void p() 
     { 
      //specific stuff 
     } 
}; 

這段代碼的目標將是在C取決於模板參數的一些方法(在這裏C<1,2>將同時擁有AB類的方法,而C<1>將只有A,然後C<1, C<1,2> >將只有一個A,而C<1, 2, C<3> >會有兩個,等等......)。 我失敗的地方在於它在專業化之前對C的聲明,因爲我不知道如何聲明足夠通用的東西來支持值和類型模板參數(在本例中爲int值和類型,混合)。 因爲如果我宣佈

template <typename ... Args> 
class C; 

它顯然無法解析整數。

而且

template <int a, int b, typename ... Args> 
class C; 

顯然無法解析類型的專業化只有一個int參數。

所以,我發現到現在爲止唯一的解決辦法是宣佈2種不同類型,而不是C

template <int a, typename ... Args> // allows first specialisations 
class C; 
template <int a, int b, typename ... Args> //allows second specialisations 
class D; 

但我想組進只有一個聲明。可能嗎 ?

預先感謝您! PS:順便說一下,我選擇的標題是非常糟糕的,如果你有更好的建議,讓我知道!

回答

1

我所能想象的最好的是聲明C爲僅接收類型

template <typename ...> 
class C; 

幷包裹在一個虛設類型的初始整數值(或使用std::integer_sequence

template <int ...> 
struct Ci 
{ }; 

顯然的C的聲明如(通過實施例)C<1>,先前

C<1> c1; 

成爲

C<Ci<1>> c1; 

以下代碼是難看但編譯

template <typename> class A {}; 
template <typename> class B {}; 

template <typename ...> 
class C; 

template <int ...> struct Ci {}; 

template <int a> 
class C<Ci<a>> : public A<C<Ci<a>>> 
{ }; 

template <int a, typename ... Other_handlers> 
class C<Ci<a>, Other_handlers...> : public A<C<Ci<a>, Other_handlers...>> 
{ }; 

template <int a, typename Child> 
class C<Ci<a>, B<Child>> : public A<C<Ci<a>, B<Child>>> 
{ }; 

template <int a, int b> 
class C<Ci<a, b>> : public B<C<Ci<a, b>> >, C<Ci<a>> 
{ }; 

template <int a, int b, typename ... Other_handlers> 
class C<Ci<a, b>, Other_handlers...> 
    : public B<C<Ci<a, b>, Other_handlers...>>, C<Ci<a>> 
{ }; 

template <int a, int b, typename Child> 
class C<Ci<a, b>, B<Child> > : public B<C<Ci<a, b>, B<Child> > >, C<Ci<a>> 
{ }; 


int main() 
{ 
    C<Ci<1>> c1; 
} 
+0

而如何實例'C '在這種情況下?類似於'C <1> c;'可能會產生錯誤。 – VTT

+0

@VTT - 舊的'C <1> c;'成爲'C > c;';或許是在答案中加入了這一點;謝謝。 – max66

0

我只能認爲醜陋的解決方案涉及的宏只允許您將導致使用類型爲單一聲明:

template<int V> struct 
fooIntImpl 
{ 
}; 

template<int V> fooIntImpl<V> 
foo_deduce_helper(void); 

template<typename T> struct 
fooTypeImpl 
{ 
}; 

template<typename T> fooTypeImpl<T> 
foo_deduce_helper(void); 

#define foo(template_parameters) decltype(foo_deduce_helper<template_parameters>()) 

int main() 
{ 
    foo(42) fooint; 
    foo(int) footype; 

    return 0; 
}