如何在部分类模板专业化中实现继承

How do I implement inheritance in a partial class template specialisation?

本文关键字:专业化 实现 继承 分类      更新时间:2023-10-16

我想我只是错过了一些小东西。我想为一个实现专门化模板类的构造函数,其中T=带有任何参数的模板类。对不起,我的嗓音有点不好。基本上,我需要允许锯齿状的2D阵列,所以我可能有一个ArEl<ArEl<int>>,我想预先初始化所有的阵列长度。

using namespace std;
template <typename T>
class ArEl {
public:
ArEl(size_t size = 0)
: rSize(size), rArray(rSize ? new T[rSize]() : nullptr) {}
ArEl(const ArEl& other);
virtual ~ArEl() { delete[] rArray; }
void swap(ArEl& first, ArEl& second);
void redim(size_t size);
private:
std::size_t rSize;
T* rArray;
};
template <typename T, typename T1>
class ArEl<ArEl<T>> : public ArEl<T1>{
ArEl(size_t size = 0);
};

编辑:

我得到这个错误:

error: template parameters not deducible in partial specialization:
class ArEl<ArEl<T>> : public ArEl<T1>{

您以错误的方式专门化对象。

template<typename T, typename T1>意味着需要提供两种数据类型,但很明显,模板专业化唯一需要的是底层数组的数据类型。如果期望ArEl<ArEl<T>>是专门化的,那么它不应该超过这个:

template<typename T>
class ArEl<ArEl<T>> {
/*Blah Blah Blah*/
};

不需要继承,也不需要第二种数据类型。

然而,我还要补充一点:一开始并没有真正需要这种专业化。如果你根本不写专业化,下面的代码应该仍然可以正常工作:

ArEl<ArEl<int>> dim2Array(50);
//I'm assuming ArEl will have a member size() function
for(size_t index = 0; index < dim2Array.size(); index++) {
//I'm assuming ArEl will have an operator[] overload
dim2Array[index].redim(30);
}
//dim2Array is now 50 int arrays, each of size 30.

我假设你想要的功能是如下所示,这确实需要像我上面发布的那样的模板专业化:

ArEl<ArEl<int>> dim2Array(50, 30);
//dim2Array is now 50 int arrays, each of size 30.

但如果我是你,我会放弃ArEl的实现,而是投资于编写一个Matrix<T>类(或者可能是Matrix<T, N>,用于N维)来处理这种语法(顺便说一句,你可以使用ArEl<T>作为构建块来构建它),尤其是因为我不认为你会致力于为ArEl<ArEl<ArEl<int>>>或更深层次编写专业知识(是的,按照你的尝试方式,每个级别都需要自己的专业知识)。

专门化整个类意味着用专门化提供的成员替换所有成员。你不想那样。

一种选择是在基类中提供所有需要专门化的成员:BaseForA<T>将是专门化的,A<T>将从中派生

另一种方法是使用标记调度,下面是一个如何使用它根据类型参数执行不同操作的示例。

#include <iostream>
#include <type_traits>
template<typename T>
struct tag {};
template<typename T>
struct A
{
private:
template<typename U>
A(std::size_t s, tag<A<U>>)
{
std::cout << "special constructor " << s << "n";
}
A(std::size_t s, ...)
{
std::cout << "general constructor " << s << "n";
}
public:
A(std::size_t s = 0) :
A(s, tag<T>())
{
}
};
int main() 
{
A<int> a;
A<A<int>> b;
A<A<long>> c;
A<long> d;
}

在Coliru 上直播

如果我理解正确,你希望专业版本继承通用版本,然后在上面添加一些东西。这里的问题是你有一个专门的ArEl<ArEl<T>>,你不能请求它的通用版本。

解决方案是使通用版本和专用版本成为不同的类型。

template<typename T, bool D=true>
class ArEl { ...
template<typename T>
class ArEl<ArEl<T>>: 
public ArEl<ArEl<T>, false> { ...

但现在的问题是ArEl<T, true>ArEl<T, false>是不相关的,不兼容的!

解决方案是为它们引入一个公共基类。

template<typename T>
class ArElBase {
... all functionality of ArEl
};
template<typename T, bool D=true>
class ArEl : public ArElBase<T> { 
using ArElBase<T>::ArElBase;
// nothing more
}; 

然后是专业化,没有变化。

现在,您可以使用ArElBase通过指针或引用传递对象,但可以使用ArEl声明对象本身。