Related:
Consider this pair of variadic templates:
template<typename Dummy>
bool All(Param& c) {
return true;
}
template<typename Dummy, Func* f, Func* ...rest>
bool All(Param& c) {
return f(c) && All<Dummy, rest...>(c);
}
This works and compiles. However, how to write it without the first template parameter?
Sounds trivial? Well, that's what I thought. :-) Let's consider some ideas.
template<Func* f, Func* ...rest>
bool All(Param& c) {
return f(c) && All<rest...>(c);
}
template<>
bool All(Param& c) {
return true;
}
Won't work... When I attempted this I had specialization in mind, but on the second thought that's not how it works.
In the original example I created two different templates of overloads, first taking 1 template parameter and second taking 2 or more. No ambiguities and no specialization involved. am I getting it right?
bool All(Param& c) {
return true;
}
template<Func* f, Func* ...rest>
bool All(Param& c) {
return f(c) && All<rest...>(c);
}
Won't work obviously, All<rest...>
with rest...
being empty won't expand to a call to a non-template function.
Let's rebuild the solution a bit.
template<Func* f>
bool All(Param& c) {
return f(c);
}
template<Func* f, Func* ...rest>
bool All(Param& c) {
return f(c) && All<rest...>(c);
}
This one is a no-go, because All(c) would be ambiguous. Hence I need to have a 0-arg case and a >0-arg case... Or what about a 1-arg case and a >1-arg case?
Idea #3.5:
template<Func* f>
bool All(Param& c) {
return f(c);
}
template<Func* f, Func* f2, Func* ...rest>
bool All(Param& c) {
return f(c) && All<f2, rest...>(c);
}
Yup, works, but contains copypasta (simple in this case but might be bigger!), hence I'd say it's no better than what I've started with. Just another workaround.
Let's try #1 but with classes instead of functions.
template<Func* f, Func* ...rest>
struct All {
static bool func(Param& c) {
return f(c) && All<rest...>(c);
}
};
template<>
struct All {
static bool func(Param& c) {
return true;
}
};
This looks promising since I can specialize classes. But hey, what is it?
sorry, unimplemented: cannot expand 'rest ...' into a fixed-length argument list
Wasn't this a GCC 4.4 thing? I'm on MinGW GCC 4.6.1 (tdm-1).
Anyway, should I think that I cannot do such an elementary thing in a straightforward way? Is it required to use the workaround with an additional dummy template parameter to accomplish this task?
Or is there a simple, correct variant to specify the zero-argument case, which would work?
In this question's case, since template parameters are non-type,
if we prepare a function with default template argument like the
following, Dummy
parameter can be saved:
template<typename = void>
bool All(Param& c) {
return true;
}
template<Func* f, Func* ...rest>
bool All(Param& c) {
return f(c) && All<rest...>(c);
}
However, I'm not sure this is always applicable.
For more general case, std::enable_if
or similar dispatch might be needed
(this will make the code a little lengthy though).
Looks like your question is similar to this one: Compilation Error on Recursive Variadic Template Function
There are two answers there that should work; one that is your #3.5 and the second is one you didnt have.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With