联合作为模板化基类的部分特化
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了联合作为模板化基类的部分特化相关的知识,希望对你有一定的参考价值。
当我从一个union
的模板化基类继承并对其进行部分特化时,MSVC上的编译失败,因为禁止将union
s作为基类(参见1)。但是,如果我使用struct
作为我继承的主要模板,并且仅使用union
进行部分特化,它可以让我编译它就好了。我很好奇为什么会这样。另外我想知道下面的代码(2)是否符合标准,或者MSVC只允许我绕过标准。
(1)C ++标准(10.4 Unions [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> {
};
此代码不合法。来自[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
是否是一个共同的初始序列。
你的部分专业化不是union
。
正如你所指出的那样,union
不能用作基类,正如Justin指出的那样,使用union
关键字进行部分特化是不合法的。
除此之外:由于某些原因,MSVC不介意使用union
关键字,只是忽略部分特化的类键,并将其视为struct
的定义。
在gcc
的情况下也会发生同样的事情。它抱怨不同的类键,但是一旦你将-fpermissive
标志传递给编译器,你的例子就会编译,尽管vector<T, 2>
是一个结构,而不是一个联合。
以上是关于联合作为模板化基类的部分特化的主要内容,如果未能解决你的问题,请参考以下文章