可变模板函数的部分特化

Partial Specialization of a variadic template function

本文关键字:函数      更新时间:2023-10-16

我有这个函数应该递归地工作。

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

现在碰巧在某些时候我碰到了一个类(Wt::WObject),它没有addStyleClass成员函数,所以编译器抱怨这个问题-正确的-。好的。所以我想专门化代码,为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)...);
    // ...
}
这个想法是将标签调度请求到内部实现(在示例中称为addStyleClassRecursiveImpl),并使用sfinae和函数重载来选择正确的版本。

当然,你不能部分专门化一个函数模板

不能部分特化函数模板。

你可以做的是让递归模板在它的第一个可变参数上调用一个不同的函数,然后在剩下的参数上递归调用它自己。然后可以完全专门化helper函数。