【问题标题】:Partial Specialization of a variadic template function可变参数模板函数的部分特化
【发布时间】:2016-11-04 14:45:56
【问题描述】:

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

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 成员函数的类 (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);
                                                                                        ^

那么任何人都可以指出如何获得所需的结果?

【问题讨论】:

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


    【解决方案1】:

    你可以这样做:

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


    当然,您不能部分特化函数模板。

    【讨论】:

    • 我必须做一些小改动才能让它工作,但实际上这是一个即插即用的解决方案。谢谢。
    • @DrHell 我是用手机写的,如有错别字还请见谅。我很高兴它对你有用。
    • 对不起,我不想听起来傲慢或其他什么,我解释说它需要一些小改动以防万一将来有人想使用它并想知道它为什么一开始不起作用跑步。再次感谢。 :)
    • @DrHell 你听起来并不傲慢!绝对地!!我只是试图解释为什么我可能犯了一些错误。 :-)
    【解决方案2】:

    您不能部分特化函数模板。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-14
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 2017-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多