我原本打算将模板用于Array风格的类,只需将它传递给char*
或int
,但在尝试实现以下内容时遇到了问题:
template<Typename T>
class Array {
void add(T elem) {
if(size == capacity) expandArr();
if(T == char*) //g++ threw errors here
arr[size] = new char[strlen(word) + 1];
strcpy(arr[size], word);
else if(T == int) {
arr[size] = elem;
}
size++;
}
}
还有另一种合法检查元素类型的方法吗?或者我应该将这两个类分开并使它们独立?
我最初尝试使用模板化类,因为两种数组类型具有相同的功能,但在这种情况下,char*
和int
'的内存分配方式存在一些根本区别。秒。
答案 0 :(得分:2)
您应该使用template specialisation为不同的模板类型设置不同的行为。
将您的代码更改为:
template<typename T>
class Array {
void add(T elem) {
if(size == capacity) expandArr();
size++;
}
}
template<>
class Array<char*> {
void add(T elem) {
if(size == capacity) expandArr();
arr[size] = new char[strlen(word) + 1];
strcpy(arr[size], word);
size++;
}
}
template<>
class Array<int> {
void add(T elem) {
if(size == capacity) expandArr();
arr[size] = elem;
size++;
}
}
答案 1 :(得分:2)
在这种情况下,类模板专业化是过度的 - 它会强制您为不同类型复制整个类,即使〜90%的功能都是相同的。
关键是要隔离那些不同的部分,并仅对这些部分进行专门化。但是出于几个原因,使用重载而不是专业化更容易。
在您的情况下,不同的部分只是为数组项赋值。
template <typename T>
class Array {
void add(T elem) {
if(size == capacity) expandArr();
assignItem(elem);
size++;
}
template <typename U>
void assignItem(U elem) {
arr[size] = elem;
}
void assignItem(char* elem) {
// Incidentally, DON’T DO THIS! It leaks. Use RAII!
arr[size] = new char[strlen(elem) + 1];
strcpy(arr[size], word);
}
};
当然,现在您已对受支持的Array
类型进行了硬编码:仅支持具有复制构造函数和 char*
的类型,而不支持其他类型。通常,您不希望出现此限制,您希望支持任意类型,并允许它们指定它们的复制方式 1 。
有几种方法可以实现这一目标。我将在这里通过一个指定如何复制类型的特征类来说明一个。
template <typename T>
struct CopyConstruct {
void assign(T& target, T source) const {
target = source;
}
};
template <typename T, typename Copy = CopyConstruct<T>>
class Array {
Copy copier;
void add(T elem) {
if(size == capacity) expandArr();
copier.assign(arr[size], elem);
size++;
}
};
此类可以与初始类完全相同。对于char*
,用户有两种选择:要么专门化CopyConstruct
,要么在实例化Array
时提供完全自己的特征,如下所示:
struct CopyCString {
void assign(char*& target, char* source) const {
target = new char[strlen(elem) + 1];
strcpy(arr[size], word);
}
};
// And then:
Array<char*, CopyCString> strArray;
(请注意,我们将引用传递给指针 - 否则分配的内存将会丢失,因为我们将指针分配给副本数组项,而不是项本身。)
1 但实际上C ++已经完全使用了复制构造函数。 真正的解决方案不是上述任何一项,而是将char*
包装成可复制的类型,例如std::string
。