当我从模板化的基类union
继承并对其进行部分专业化处理时,在MSVC上的编译失败,因为它禁止将union
作为基类(请参见1)。
但是,如果我将struct
用于我继承的主模板,而仅将union
用于部分专业化,那么我可以对其进行编译。
我很好奇为什么会这样。另外,我想知道下面的代码(2)是否符合标准,还是MSVC只允许我绕过该标准。
(1)C ++标准(10.4联合[class.union])
“联合可以具有成员函数(包括构造函数和 析构函数),但它不应具有虚拟(10.6.2)函数。一种 工会不得有基层。 不得将工会用作 基本类。”
(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> {
};
答案 0 :(得分:4)
此代码不合法。来自[temp.class]:
在重新声明,部分专门化,显式专门化或显式实例化类模板时,类密钥应与原始类模板声明([dcl.type.elab])保持一致。
class-key是class
,struct
或union
之一。
在您的情况下,您的部分专业化是非法的,因为以前使用union
时使用了struct
的类键。
要获得所需的行为,请在课程内部使用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
是常见的初始序列。
答案 1 :(得分:1)