给出这样的模板类:
template <typename T>
class C
{
T member;
//... some other members that are not of interest here
};
我可以提供任何类型的T来阻止member
占用不必要的内存吗?
起初void
突然出现在我的脑海中,但我知道您无法声明void
的变量。
注
当然,这个例子是简化的。后台是一个包含一些信息的类,但可以获取用户添加的其他信息。当用户不想添加其他信息时,应该可以将其删除。所以基本上如果用户想要存储其他数据,他将构建C<MyAdditionalData>
,但如果他不这样做,它应该像C<NoData>
那样,并且没有数据。当然,我可以写一些模板专业化,但我不喜欢写两次。
修改
好吧,我发现一个空类是我能得到的最接近的(由于对齐,仍然消耗1个字节甚至4/8),所以现在我的问题是:
我是否应该使用一些标准的空类来使我的代码更具可读性?
答案 0 :(得分:5)
为类型NoData
专门化您的模板类,并且不要在此专业化中定义成员。
template <class T>
class C {
T member;
...
};
template<>
class C<NoData> {
// Do not declare that member
};
答案 1 :(得分:3)
好的,我发现一个空类是我到目前为止最接近的,所以现在我的问题是:我是否应该使用一些标准空类来制作我的代码更具可读性?
没有。您可以自己定义一个:
struct standard_empty_class {};
使用它。
所以基本上如果用户想要存储其他数据,他将构建
C<MyAdditionalData>
,但如果不存在,则应该像C<NoData>
那样,并且没有数据。
我不明白这一点。如果用户不想存储任何数据,那么为什么即使你需要一个类,仍然需要编写C<NoData>
?忘了那个案子。没有数据意味着没有课程。它解决不了吗?
答案 2 :(得分:2)
我不认为这是可能的。实际上,这是另一种方式。即使空类在实例化时占用内存(一个字节),因此程序可以在实例之间有所不同。那是
class A {
};
A a, b; // vars of type A
然后a
和b
必须占用一些内存,以便您的程序可以引用它们,例如if (a == b)
。如果他们不使用记忆,你就不能这样做。
答案 3 :(得分:2)
使用数据成员no,因为对象永远不会为零,并且数据成员没有get-out子句。
但是,如果基类子对象为空,则其大小为零。因此:
template <typename T>
struct Member {
T member;
};
template <>
struct Member<void> {
};
template <typename T>
class C : private Member<T>
{
//... some other members that are not of interest here
};
我想,应该有效。但是你可能会因为C<void>::member
不存在这一事实而绊倒,因此任何使用它的成员函数都不会为C<void>
编译,包括构造函数。
如果用户想要存储他将构建的其他数据
C<MyAdditionalData>
为什么没有C
非模板类而没有其他数据成员,如果用户想要添加数据成员,请使用C
作为基类?记得给C
一个受保护的析构函数 - 每个基类都应该有受保护的析构函数或虚拟析构函数,但由于你的C
模板类没有虚拟析构函数,所以不需要非模板版本也是虚拟的。
沿着这些方向,您可以这样做:
class CNoData
{
//... some other members that are not of interest here
};
template <typename T>
class CWithData<T> : CNoData
{
T member
// have to duplicate constructors, unfortunately.
};
如果你真的需要它,添加一个类型特征:
template <typename T>
struct C {
typedef CWithData<T> type;
};
template <>
struct C<void> {
typedef CNoData type;
};
然后你会写C<MyAdditionalData>
,现在你写CWithData<MyAdditionalData>
,你写C<some_type_that_might_be_void>
的地方就写typename C<some_type_that_might_be_void>::type
。
答案 4 :(得分:1)
正如您所说,模板已包含一些其他数据。它有虚拟方法,那就是另一个成员。
添加一个额外的成员是一个非常小的开销,可以简单地忽略,所以我只使用C.(如果有其他成员小于对齐,甚至是char)
使用typedef更清晰:
typedef C<int> CEmptyGraphNode;