不同的功能取决于模板类中的类型
Different functionality depending on type in templated classes
我本来打算为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++;
}
}
是否有其他合法检查元素类型的方法?还是我应该把这两个班分开,让它们独立?
我最初尝试使用模板化类,因为两种Array类型具有相同的功能,但在这种情况下,char*
和int
的内存分配方式存在一些根本差异。
在这种情况下,类模板专业化有些过头了——它迫使您为不同的类型复制整个类,即使大约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。
实现这一点有几种方法。我将在这里通过一个指定如何复制类型的trait类来说明一个。
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
。
您应该使用模板专业化来为不同的模板类型提供不同的行为。
将您的代码更改为:
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++;
}
}
相关文章:
- SFINAE是否取决于类型推断?
- 将强制转换简化为取决于参数的类型
- cpp 模板专用化,错误说参数 1 的类型为 T,这取决于参数 T
- 编译时函数的选择取决于类型大小
- memcpy是否取决于源指针和目标指针的类型
- 如果条件取决于模板类型并且在编译时已知,是否可以保证C++编译器不会生成分支?
- 执行特定函数取决于类型
- 模板函数,其中模板参数类型取决于函数参数
- clang 拒绝具有尾随 decltype 返回类型的模板调用是否正确,具体取决于其重载之一?
- 基类数据成员类型取决于派生类
- 类型取决于模板中的条件
- 如何在基本模板类中声明成员,其中类型取决于派生类的类型
- 如何将函数指针声明指向模板函数,其返回类型取决于模板类
- 返回类型取决于模板参数
- 模板化结构的友元函数,其参数类型取决于结构的内部
- 变量模板函数,其中返回类型取决于模板参数列表
- C++ 模板返回类型取决于模板参数
- 返回类型取决于静态参数包字段
- 模板类的不同返回类型取决于类的形参
- 返回类型取决于算术运算的顺序.对吗?