I recently came across the following:
// declare
template <class> struct A;
// specialise
template <template <class...> class C, class... Fields> struct A<C<Fields...>> {
template <typename... Args> explicit A(C<Fields...>* c, Args&&... args) {}
};
// instantiate
template <template <class...> class C, class... Fields, class... Args>
A<C<Fields...>> MakeA(C<Fields...>* c, Args&&... args) {
return A<C<Fields...>>(c, std::forward<Args>(args)...);
}
If I understand it correctly (comments above are mine), it is declaring A as a template, then specialising A, and the rest is more or less straightforward.
Why do we need to do this instead of being able to directly define the template, something like the following (which compiles and seems to be otherwise functional as far as I can tell):
template <template <typename...> class C, typename... Fields> struct A1 {
public:
template <typename... Args> explicit A1(C<Fields...>* c, Args&&... args) {}
};
template <template <typename...> class C, typename... Fields, typename... Args>
A1<C, Fields...> MakeA1(C<Fields...>* c, Args&&... args) {
return A1<C, Fields...>(c, std::forward<Args>(args)...);
}
My question is both approaches are equally valid/acceptable/technically correct? If yes, is one preferable for some subtle technical or aesthetic reasons and why?
For additional context, I did not see any other specialisations in the original code so I'm not sure what the code with the specialisation buys us.