I have this function which should work recursively.
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...);
}
}
Now it happens that at some point I hit a class ( Wt::WObject
) which has not the addStyleClass
member function, so the compiler complains -rightly- about this problem. Ok. So I thought to specialize the code, adding a version for 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...);
}
}
This doesn't give a compiler error in itself, but it is utterly ignored (indeed the compiler keeps complaining about WObject
not having the required member function, pointing to the same line within the general function).
So I tried to specialize it in this way
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...);
}
}
Now the compiler complains about
non-type partial specialization 'addStyleClassRecursive<Wt::WObject, Arguments ...>' is not allowed
void addStyleClassRecursive<Wt::WObject, Arguments...>(Wt::WObject *c, Arguments... arg);
^
So can anyone point out how to attain the required result?
You cannot partially specialize a function template.
What you can do is let the recursive template call a different function on its first variadic template arg, and then recursively call itself on the remainder of the arguments. Then you can fully specialize the helper function.
You can do something like this:
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)...);
// ...
}
The idea is to tag-dispatch the request to an internal implementation (called addStyleClassRecursiveImpl
in the example) and use sfinae and function overloading to pick the right version up.
And of course, you cannot partially specialize a function template.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.