过多限制特化的 C++ 模板声明

C++ template declaration that restricts specializations too much

我将尝试简要解释一下我当前的问题。它可以很容易地解决,但到目前为止我找到的唯一解决方案并不令我满意,也许你会向我指出解决问题所需的下一个间接级别。

我在这里使用 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> 将有 A 和 [=17 的方法=] class,而 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 : 顺便说一句,我选的标题很糟糕,如果您对此有更好的建议,请告诉我!

我只能想到涉及宏的丑陋解决方案,它只允许您将结果类型用法分组到一个声明中:

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;
}

我能想到的最好的方法是将 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;
 }