在这种情况下,类模板专业化是多余的——它迫使你为不同的类型复制整个类,即使大约 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*
,用户有两种选择:要么 specialize CopyConstruct
,要么在实例化时提供完全自己的 trait 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
.