展开可变参数模板结构

Unwrapping variadic template structs

我正在尝试创建一个 variant 结构,即包含这么多类型之一的结构。到目前为止,这是我的尝试:

template <typename Type, typename... Rest> struct OneOf {
    union {
        Type value;
        OneOf<Rest...> rest;
    };
};

template <typename Type> struct OneOf {
    Type value;
};

遗憾的是,这无法编译。当我尝试实例化它时,我得到:

one_of.h:34:33: error: redeclared with 1 template parameter template struct OneOf {

有没有办法终止使用结构的自引用递归?

怎么样

template <typename...>
struct OneOf;

template <typename Type, typename... Rest>
struct OneOf<Type, Rest...> {
    union {
        Type value;
        OneOf<Rest...> rest;
    };
};

template <>
struct OneOf<> {
};

?

O也

template <typename, typename...>
struct OneOf;

template <typename T0, typename T1, typename ... Ts>
struct OneOf<T0, T1, Ts...> {
    union {
        T0 value;
        OneOf<T1, Rest...> rest;
    };
};

template <typename T0>
struct OneOf<T0> {
    T0 value;
};

?

我假设您正在尝试编写专业化。

这是语法:

template <typename Type> struct OneOf<Type> {
//                                   ^~~~~~
    Type value;
};

您必须首先声明主模板,然后声明任何专业化(全部或部分)。主模板决定了模板参数的数量和种类。实例化模板时,如果完全匹配则使用完全特化,如果匹配则使用最匹配的部分特化,否则将实例化主模板。

如果您希望 OneOf 成为一个接受任意数量的类型模板参数(0 个或更多)的模板,那么您应该相应地声明主模板:

template <class... T> struct OneOf;

然后你需要两个特化:一个用于递归的基本情况,可以看作是空包:

template <>
struct OneOf<> {};

还有一个用于递归情况,至少有一个模板参数:

template <typename Type, typename... Rest> struct OneOf<Type, Rest...> {
    union {
        Type value;
        OneOf<Rest...> rest;
    };
};

请注意,完全特化和部分特化都需要在模板名称后添加模板参数列表。如果你忽略这个,编译器会认为你正在重新声明主模板,这会导致你看到的错误。