可变参数模板函数的部分特化

时间:2016-11-04 14:45:56

标签: c++ function templates variadic-templates partial-specialization

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

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没有所需的成员函数,指向一般函数中的同一行。 / p>

所以我试图以这种方式专门化

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);
                                                                                        ^

那么有人能指出如何获得所需的结果吗?

2 个答案:

答案 0 :(得分:2)

您不能部分专门化功能模板。

你可以做的是让递归模板在其第一个可变参数模板arg上调用另一个函数,然后在其余参数上递归调用自身。然后你可以完全专门化辅助函数。

答案 1 :(得分:2)

您可以这样做:

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 和函数重载来选择正确的版本。

当然,您不能部分专门化功能模板。