You have to first declare the primary template, and then declare any specializations (either full or partial). The primary template determines the number and kind of template arguments. When it comes time to instantiate the template, a full specialization will be used if it matches exactly, or the best-matching partial specialization if any match, otherwise, the primary template will be instantiated.
If you want OneOf
to be a template that takes any number of type template arguments (0 or more), then you should declare the primary template accordingly:
template <class... T> struct OneOf;
Then you'll need two specializations: one for the base case of the recursion, which can be taken to be the empty pack:
template <>
struct OneOf<> {};
and one for the recursive case, with at least one template parameter:
template <typename Type, typename... Rest> struct OneOf<Type, Rest...> {
union {
Type value;
OneOf<Rest...> rest;
};
};
Notice that both full and partial specializations require a template argument list after the template name. If you omit this, the compiler will think you are redeclaring the primary template, which causes the error you're seeing.