过多限制特化的 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;
}
我将尝试简要解释一下我当前的问题。它可以很容易地解决,但到目前为止我找到的唯一解决方案并不令我满意,也许你会向我指出解决问题所需的下一个间接级别。
我在这里使用 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;
}