使用模板有条件地生成c++类的数据成员
Using templates to conditionally generate data members of a C++ class
我有一个类,它作为一组固定范围内的整数工作0…可以很容易地处理添加新元素、删除元素、清空集合以及检查整数是否属于集合的一部分。下面是类的代码。
同样,从代码中可以看出,如果选项COMPUTE_SET_SIZE
存在,则类计算集合的大小,如果选项COMPUTE_LINKED_LIST
存在,则可以使用类有效地枚举集合元素。
现在,问题是枚举集合元素在内存使用方面是一个繁重的操作,而且很多时候,它是不需要的。因此,我希望以某种方式能够仅在需要时生成这些代码部分,而不必维护两个不同的类(一个具有此功能,另一个没有)。
我明白模板(如std::enable_if)可以用来实现类似的目标,但我不明白如何使用它们来有条件地生成数据成员,如下面代码中的prev和next。
#ifndef _FIXED_SIZE_INT_SET_H_
#define _FIXED_SIZE_INT_SET_H_
#include <cstring>
#include <assert.h>
#define COMPUTE_SET_SIZE
#define COMPUTE_LINKED_LIST
class FixedSizeIntSet
{
private:
const int MAX_TAG = 1000000000;
int capacity;
int currentTag;
int *tags;
#ifdef COMPUTE_SET_SIZE
int size;
#endif
#ifdef COMPUTE_LINKED_LIST
int start;
int *next;
int *prev;
#endif
void initialize() { memset(tags, 0, capacity * sizeof(int)); }
public:
FixedSizeIntSet(int capacity)
{
this->capacity = capacity;
this->currentTag = 1;
tags = new int[capacity];
#ifdef COMPUTE_SET_SIZE
size = 0;
#endif
#ifdef COMPUTE_LINKED_LIST
start = -1;
next = new int[capacity];
prev = new int[capacity];
#endif
initialize();
}
void insert(int n)
{
assert((n >= 0) && (n < capacity));
#ifdef COMPUTE_SET_SIZE
if (tags[n] != currentTag) size++;
#endif
#ifdef COMPUTE_LINKED_LIST
if (tags[n] != currentTag)
{
next[n] = start;
prev[n] = -1;
if (start >= 0)
prev[start] = n;
start = n;
}
#endif
tags[n] = currentTag;
}
void remove(int n)
{
if ((n >= 0) && (n < capacity))
{
#ifdef COMPUTE_SET_SIZE
if (tags[n] == currentTag) size--;
#endif
#ifdef COMPUTE_LINKED_LIST
if (tags[n] == currentTag)
{
if (next[n] >= 0)
prev[next[n]] = prev[n];
if (prev[n] >= 0)
next[prev[n]] = next[n];
else
start = next[n];
}
#endif
tags[n] = 0;
}
}
void clear()
{
if (currentTag < MAX_TAG)
currentTag++;
else { initialize(); currentTag = 1; }
#ifdef COMPUTE_SET_SIZE
size = 0;
#endif
#ifdef COMPUTE_LINKED_LIST
start = -1;
#endif
}
bool hasMember(int n) { return ((n >= 0) && (n < capacity)) ? (currentTag == tags[n]) : false; }
#ifdef COMPUTE_LINKED_LIST
int begin() { return start; }
int end() { return -1; }
int nextNumber(int curNumber) { assert((curNumber >= 0) && (curNumber < capacity)); return next[curNumber]; }
#endif
};
#endif
理想情况下,我想要这样的代码:
template <bool enableEnumeration>
class FixedSizeIntSet {
....
}
使得FixedSizeIntSet<false>
不计算链表(也没有关联的数据成员),而FixedSizeIntSet<true>
计算链表
这里有一个方法来解决你的设计问题。
类定义。
#ifndef _FIXED_SIZE_INT_SET_H_
#define _FIXED_SIZE_INT_SET_H_
#include <cstring>
#include <assert.h>
template <typename Trait>
class FixedSizeIntSet : public Trait
{
private:
const int MAX_TAG = 1000000000;
int capacity;
int currentTag;
int *tags;
void initialize() { memset(tags, 0, capacity * sizeof(int)); }
public:
FixedSizeIntSet(int capacity) : Trait(capacity)
{
this->capacity = capacity;
this->currentTag = 1;
tags = new int[capacity];
initialize();
}
void insert(int n)
{
assert((n >= 0) && (n < capacity));
if (tags[n] != currentTag)
{
Trait::insert();
}
tags[n] = currentTag;
}
void remove(int n)
{
if ((n >= 0) && (n < capacity))
{
if (tags[n] == currentTag)
{
Trait::remove(n);
}
tags[n] = 0;
}
}
void clear()
{
if (currentTag < MAX_TAG)
currentTag++;
else { initialize(); currentTag = 1; }
Trait::clear();
}
bool hasMember(int n) { return ((n >= 0) && (n < capacity)) ? (currentTag == tags[n]) : false; }
};
#endif
用法:
struct ComputeSetSize
{
ComputeSetSize(int ) : size(0) {}
void insert(int ) { ++size; }
void remove(int ) { --size; }
void clear() { size = 0; }
int size;
};
struct ComputeLinkedList
{
ComputeLinkedList(int capacity)
{
start = -1;
next = new int[capacity];
prev = new int[capacity];
}
void insert(int n)
{
next[n] = start;
prev[n] = -1;
if (start >= 0)
prev[start] = n;
start = n;
}
void remove(int n)
{
if (next[n] >= 0)
prev[next[n]] = prev[n];
if (prev[n] >= 0)
next[prev[n]] = next[n];
else
start = next[n];
}
void clear()
{
start = -1;
}
int begin() { return start; }
int end() { return -1; }
int nextNumber(int curNumber) { assert((curNumber >= 0) && (curNumber < capacity)); return next[curNumber]; }
int capacity;
int size;
int start;
int *next;
int *prev;
};
int main()
{
FixedSizeIntSet<ComputeSetSize> set1(10);
FixedSizeIntSet<ComputeLinkedList> set2(20);
}
相关文章:
- 用于访问容器<T>数据成员的正确 API
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 数据成员SFINAE的C++17测试:gcc vs clang
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 如何在c++中定义以struct为数据成员的类中的构造函数
- 静态数据成员模板专用化的实例化点在哪里
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 使用指针访问数组中的对象数据成员
- 友元函数无法访问私有数据成员 (c++)
- 我可以在 C++ 中将数据成员/变量从其定义之外添加到结构中吗?
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- 将私有数据成员添加到野牛生成的类中
- 输入数据成员未按要求工作
- 二维矢量数据成员
- 在类 A 中创建类型为 B 类的向量 - 访问数据 [C++] [成员在两个类中都是私有的]
- 调用在 HXX 文件中声明的静态数据成员
- 是否可以根据其数据成员的类型确定类型的大小
- 访问数据成员(本身是对象)的数据成员,就好像它们是类成员一样
- 使公共数据成员在C++中无法访问
- 从 XML 中读取未指定结构的每个数据成员