I've been following the work on
P1858 and just yesterday it occurred to me that it'd be useful to do something like this:
template <typename... Ts>
rtype<Ts> func(ptype<Ts>) ... = 0;
template <typename... Ts>
struct Implementation: Interface<Ts...>
rtype<Ts> func(ptype<Ts> p) override
where rtype<>, ptype<> and impl<> are fictional templates with exposition-only purpose.
Interesting idea, but it puts the '...' much too inconspicuously for my liking. The compiler would have to parse the entire function body before it'd be able to diagnose a missing '...' in the signature!
template<class... Ts>
struct X {
void f(Ts ts) {
}
};
^ error: '}' where '...' was expected; did you forget a '...' before 'ts' on line 3?
Besides, recursive templates aren't needed here. You could simulate what you seem to want by just doing
template<class T>
struct Interface {
virtual rtype<T> func(ptype<T>) = 0;
};
template<class T>
struct ImplDetail : Interface<T> {
rtype<T> func(ptype<T> p) override { impl<T>(p); }
};
template<class... Ts>
struct Implementation : ImplDetail<Ts>... {};
This does involve one layer of indirection (the ImplDetail layer), but it's not recursive (not even in the colloquial sense of "recursive templates") and it's legal all the way back to C++11 IIRC.
As a possible usability bonus, this implementation makes it so that `Implementation<Cat, Dog, Snake>` publicly derives from `Interface<Dog>`. In your version, there is no `Interface<Dog>` class at all, and `Interface<Cat, Dog, Snake>` is a different type from `Interface<Dog, Snake, Cat>`.
HTH,
Arthur