我有一个类在一些固定范围内作为一组整数工作 0 ... n并且可以轻松处理添加新元素,删除元素,清空集合以及检查整数是否是集合的一部分。遵循该类的代码。
此外,从代码中可以看出,如果选项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>
不计算链表(并且没有关联的数据成员)。
答案 0 :(得分:2)
这是解决您的设计问题的一种方法。
班级的定义。
#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);
}