【问题标题】:Unions as a partial specialization of a templated base class联合作为模板化基类的部分特化
【发布时间】:2018-08-03 21:27:57
【问题描述】:

当我从 union 的模板化基类继承并对其进行部分特化时,MSVC 上的编译失败,因为禁止将 unions 作为基类(参见 1)。 但是,如果我将struct 用作我继承自的主模板,并且仅将union 用于部分专业化,它可以让我很好地编译它。 我很好奇为什么会这样。另外我想知道下面的代码 (2) 是符合标准还是 MSVC 只允许我绕过标准。

(1) C++ 标准(10.4 联合 [class.union])

"联合可以有成员函数(包括构造函数和 析构函数),但它不应具有虚拟(10.6.2)函数。一种 union 不应有基类。 工会不得用作 基类。”

(2) 示例 (godbolt.org)

//template <typename T, std::size_t Size>
//↓             ↓   clearly illegal
//union vector_base {
//    vector_base() : data() {}
//    std::array<T, Size> data;
// }

template <typename T, std::size_t Size>
//↓ legal now?
struct vector_base
{
  std::array<T, Size> data;
};

template <typename T>
union vector_base<T, 2>
{
    std::array<T, 2> data;
    struct { T x, y; };
};

template <typename T, std::size_t Size>
class vector : public vector_base<T, Size> {
};

【问题讨论】:

  • 我认为您发现了一个 MSVS 错误/“功能”。 AFAIK,您不能专门化具有不同类类型的模板(从 structunion) g++ 和 clang 都无法编译:godbolt.org/g/3VDzPM
  • @NathanOliver:有趣的是,g++ 在这里抱怨别的东西(部分专业化是union 而不是struct)。如果你通过-fpermissive,代码编译(带有警告)。
  • 你真的需要x 成员而不是getter T&amp; x() { return data[0]; } 吗?

标签: c++ templates template-meta-programming


【解决方案1】:

此代码不合法​​。来自[temp.class]

在类模板的重新声明、部分特化、显式特化或显式实例化中,类键应与原始类模板声明([dcl.type.elab])实物一致。

class-keyclassstructunion 之一。

在您的情况下,您的部分特化是非法的,因为您在之前使用 struct 时使用了 union 的类键。


要获得您想要的行为,请在类中使用anonymous union

template <typename T>
struct vector_base<T, 2>
{
    union {
        std::array<T, 2> data;
        // Note that anonymous structs are non-standard, but supported in C11
        struct { T x, y; };
    };
};

但是,要小心这个union;您可能很想访问非活动成员,但这是undefined behavior,除非工会成员共享common initial sequence。在这种情况下我不确定他们是否这样做,但我认为他们没有,因为std::array 是与T[2] 不同的类型,我什至不确定T[2]T x, y 是否会是共同的初始序列。

【讨论】:

    【解决方案2】:

    您的部分专业化不是union

    正如您所指出的,union 不能用作基类,并且正如 Justin 所指出的,使用 union 关键字进行部分特化是不合法的。

    补充:由于某种原因,MSVC 不介意使用 union 关键字,而只是忽略部分特化的类键并将其视为 struct 的定义。

    gcc 也会发生同样的情况。它抱怨不同的类键,但是一旦您将-fpermissive 标志传递给编译器,您的示例就会编译,尽管vector&lt;T, 2&gt; 是一个结构,而不是一个联合。

    Demo

    【讨论】:

    • 我猜他们至少应该在这里添加一个警告。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多