可变参数模板函数的部分特化
Partial Specialization of a variadic template function
我有这个函数应该递归工作。
template <class C, typename ...Arguments>
void addStyleClassRecursive(C *c, Arguments... arg)
{
c->addStyleClass(arg...);
for (unsigned int i=0; i<c->children().size(); ++i)
{
addStyleClassRecursive(c->children()[i], arg...);
}
}
现在碰巧在某个时候我遇到了一个没有 addStyleClass
成员函数的 class (Wt::WObject
),所以编译器 - 正确地 - 抱怨这个问题。
好的。所以我想专门编写代码,为 Wt::WObject
:
添加一个版本
template <class C=Wt::WObject, typename ...Arguments>
void addStyleClassRecursive(Wt::WObject *c, Arguments... arg)
{
for (unsigned int i=0; i<c->children().size(); ++i)
{
addStyleClassRecursive(c->children()[i], arg...);
}
}
这本身并没有给出编译器错误,但它被完全忽略了(实际上编译器一直抱怨 WObject
没有所需的成员函数,指向通用函数中的同一行) .
所以我试着用这种方式专门化它
template <typename ...Arguments>
void addStyleClassRecursive<Wt::WObject, Arguments...>(Wt::WObject *c, Arguments... arg)
{
for (unsigned int i=0; i<c->children().size(); ++i)
{
addStyleClassRecursive(c->children()[i], arg...);
}
}
现在编译器抱怨
non-type partial specialization 'addStyleClassRecursive<Wt::WObject, Arguments ...>' is not allowed
void addStyleClassRecursive<Wt::WObject, Arguments...>(Wt::WObject *c, Arguments... arg);
^
所以谁能指出如何达到要求的结果?
您不能部分特化函数模板。
您可以做的是让递归模板在其第一个可变模板参数上调用不同的函数,然后在其余参数上递归调用自身。然后你可以完全特化辅助函数。
你可以这样做:
template <class C, typename ...Arguments>
auto addStyleClassRecursiveImpl(int, C *c, Arguments... arg)
-> decltype(c->addStyleClass(arg...), void()) {
c->addStyleClass(arg...);
// ... C has addStyleClass
}
template <class C, typename ...Arguments>
void addStyleClassRecursiveImpl(char, C *c, Arguments... arg) {
// ... C has not addStyleClass
}
template <typename... T>
void addStyleClassRecursive(T ...&&t) {
addStyleClassRecursiveImpl(0, std::forward<T>(t)...);
// ...
}
想法是tag-dispatch请求到内部实现(示例中称为addStyleClassRecursiveImpl
)并使用sfinae 和函数重载以选择正确的版本。
当然,您不能部分特化函数模板。
我有这个函数应该递归工作。
template <class C, typename ...Arguments>
void addStyleClassRecursive(C *c, Arguments... arg)
{
c->addStyleClass(arg...);
for (unsigned int i=0; i<c->children().size(); ++i)
{
addStyleClassRecursive(c->children()[i], arg...);
}
}
现在碰巧在某个时候我遇到了一个没有 addStyleClass
成员函数的 class (Wt::WObject
),所以编译器 - 正确地 - 抱怨这个问题。
好的。所以我想专门编写代码,为 Wt::WObject
:
template <class C=Wt::WObject, typename ...Arguments>
void addStyleClassRecursive(Wt::WObject *c, Arguments... arg)
{
for (unsigned int i=0; i<c->children().size(); ++i)
{
addStyleClassRecursive(c->children()[i], arg...);
}
}
这本身并没有给出编译器错误,但它被完全忽略了(实际上编译器一直抱怨 WObject
没有所需的成员函数,指向通用函数中的同一行) .
所以我试着用这种方式专门化它
template <typename ...Arguments>
void addStyleClassRecursive<Wt::WObject, Arguments...>(Wt::WObject *c, Arguments... arg)
{
for (unsigned int i=0; i<c->children().size(); ++i)
{
addStyleClassRecursive(c->children()[i], arg...);
}
}
现在编译器抱怨
non-type partial specialization 'addStyleClassRecursive<Wt::WObject, Arguments ...>' is not allowed
void addStyleClassRecursive<Wt::WObject, Arguments...>(Wt::WObject *c, Arguments... arg);
^
所以谁能指出如何达到要求的结果?
您不能部分特化函数模板。
您可以做的是让递归模板在其第一个可变模板参数上调用不同的函数,然后在其余参数上递归调用自身。然后你可以完全特化辅助函数。
你可以这样做:
template <class C, typename ...Arguments>
auto addStyleClassRecursiveImpl(int, C *c, Arguments... arg)
-> decltype(c->addStyleClass(arg...), void()) {
c->addStyleClass(arg...);
// ... C has addStyleClass
}
template <class C, typename ...Arguments>
void addStyleClassRecursiveImpl(char, C *c, Arguments... arg) {
// ... C has not addStyleClass
}
template <typename... T>
void addStyleClassRecursive(T ...&&t) {
addStyleClassRecursiveImpl(0, std::forward<T>(t)...);
// ...
}
想法是tag-dispatch请求到内部实现(示例中称为addStyleClassRecursiveImpl
)并使用sfinae 和函数重载以选择正确的版本。
当然,您不能部分特化函数模板。