C++ C+;中具有底层基于模板的内存管理的泛型矩阵类+;

C++ C+;中具有底层基于模板的内存管理的泛型矩阵类+;,c++,templates,matrix,C++,Templates,Matrix,我正在编写一个基于cuda的图像处理库,主要是为了好玩和学习,因为opencv的cuda源代码中已经有很多算法和操作 我想做的是对函数的输入进行一般化,这样我就可以将cuda内核应用于不同的数据类型(即8位图像和16位灰度图像),但我很难获得一个模板和继承的良好工作示例。我尝试的是多重继承,没有运气 例如,我在gimage.h中有以下函数 void GIMAGE_EXPORT test(Matrix a, Matrix b, Matrix out, int size); 类矩阵如下所示(它只是

我正在编写一个基于cuda的图像处理库,主要是为了好玩和学习,因为opencv的cuda源代码中已经有很多算法和操作

我想做的是对函数的输入进行一般化,这样我就可以将cuda内核应用于不同的数据类型(即8位图像和16位灰度图像),但我很难获得一个模板和继承的良好工作示例。我尝试的是多重继承,没有运气

例如,我在gimage.h中有以下函数

void GIMAGE_EXPORT test(Matrix a, Matrix b, Matrix out, int size);
类矩阵如下所示(它只是一个抽象类)

class GIMAGE\u导出矩阵{
公众:
矩阵(类型、大小);
类型类型();
size_t size();
模板
T*数据(){
返回空ptr;
}
私人:
大小(t)大小;;
类型_类型;
};
这才是有趣的地方。我有一个名为InputArray的模板类,负责实际的内存管理

template<typename T>
    class GIMAGE_EXPORT InputArray {
    public:
        InputArray() {
            _size = 0;
        }

        InputArray(size_t size) {
            _size = size;
            allocate(size);
        }

        ~InputArray() {
            delete[] data;
        }

        T* getData() {
            return data;
        }

        T get(int index) {
            return data[index];
        }

        void setData(T elem, int index) {
            data[index] = elem;
        }

        size_t totalSize() {
            return sizeof(T)*_size;
        }

        size_t size() {
            return _size;
        }
    private:
        void allocate(size_t size) {
            data = new T[size];
        }
        size_t _size;
        T* data;
    };
模板
类GIMAGE_导出输入阵列{
公众:
输入阵列(){
_尺寸=0;
}
输入阵列(大小\u t大小){
_大小=大小;
分配(大小);
}
~InputArray(){
删除[]数据;
}
T*getData(){
返回数据;
}
T get(int索引){
返回数据[索引];
}
void setData(T元素,int索引){
数据[索引]=元素;
}
大小\u t总大小(){
返回大小f(T)*\u大小;
}
大小{
返回大小;
}
私人:
无效分配(大小\u t大小){
数据=新T[尺寸];
}
大小(t)大小;;
T*数据;
};
然后我制作了矩阵的特定版本,即MatrixUint16和MatrixUint8。它们都继承自矩阵,但也分别继承自InputArray和InputArray的专门化

这些类如下所示(array.h)

class GIMAGE\u导出矩阵uint16:public矩阵,public InputArray{
公众:
MatrixUint16(大小);
uint16_t*数据();
};
GIMAGE_导出矩阵类uint8:公共矩阵,公共输入矩阵{
公众:
MatrixUint8(大小);
uint8_t*数据();
};
以及定义:(array.cpp)

Matrix::Matrix(类型、大小){
_大小=大小;
_类型=类型;
}
类型矩阵::类型(){
返回型;
}
大小矩阵::大小(){
返回大小;
}
MatrixUint16::MatrixUint16(大小):矩阵(类型UINT16,大小),输入阵列(大小){
}
uint16_t*MatrixUint16::data(){
返回getData();
}
MatrixUint8::MatrixUint8(大小):矩阵(类型,大小),输入数组(大小){
}
uint8_t*矩阵uint8::data(){
返回getData();
}
现在,当我像这样测试阵列时(使用GTEST)

gimage::matrixuint16a(3);
对于(int i=0;i<3;i++){
a、 setData((uint16_t)i,i);
}
期望q(a.get(0),0);
期望q(a.get(1),1);
期望q(a.get(2),2);
一切顺利,测试通过

现在在我的函数(void test(blah…)中,我尝试通过执行以下操作获取原始数据指针:

uint16_t* data = a.data<uint16_t>();
uint16_t*data=a.data();
但是如果我试图从数组中读取任何内容(即数据[0]),我会得到一个SEH异常

有没有办法让我的函数的输入保持通用,然后在运行时找出其中的数据类型?我需要知道这一点,因为我必须在调用内核之前将内存分配给GPU,所以我需要显式类型的大小(即sizeof(uint16_t)*numelements)

我基本上是在寻找与opencv::Mat相同的(ish)功能,但不需要太多的复杂性(我不需要支持所有可能的图像类型)

我应该注意的是,我不能将函数设置为模板,因为这样它就必须在头文件中定义,并且库只能在.cu文件中使用。我想生成一个可以链接到C++代码并使用它的DLL,以便所有的GPU代码都在DLL中被用户隐藏。p> 如果有人能为我想做的事情提供任何其他选择,那就太好了


为了完整起见,可以在此处查看该库:

您的矩阵不是抽象的。当您请求
.data()
时,此实现称为:

    template<typename T>
    T* data() {
        return nullptr;
    }
模板
T*数据(){
返回空ptr;
}
不能使用虚拟模板方法:无法使用模板抽象方法

你的设计不切实际

一个纯虚拟的
get\u data\u internal
可以返回一个
void*
,并让你的1get\u data
执行一个
静态强制转换(get\u data\u internal())
可能会解决你的问题,但是我看不到一个带有多态存储的普通
Matrix`类的实用性,所以我不知道这是否是个好主意


我将实现一些具体的矩阵类型,并使用traits类映射到它们,或者从库中手动导出一组模板,或者在公开的模板填充中按大小包装特定的内存类型,或者诸如此类。

您的矩阵不是抽象的。当您请求
.data()
时,此实现称为:

    template<typename T>
    T* data() {
        return nullptr;
    }
模板
T*数据(){
返回空ptr;
}
不能使用虚拟模板方法:无法使用模板抽象方法

你的设计不切实际

一个纯虚拟的
get\u data\u internal
可以返回一个
void*
,并让你的1get\u data
执行一个
静态强制转换(get\u data\u internal())
可能会解决你的问题,但是我看不到一个带有多态存储的普通
Matrix`类的实用性,所以我不知道这是否是个好主意

我将实现一些具体的矩阵类型和用法
gimage::MatrixUint16 a(3);
for (int i = 0; i < 3; i++) {
    a.setData((uint16_t)i, i);
}
EXPECT_EQ(a.get(0), 0);
EXPECT_EQ(a.get(1), 1);
EXPECT_EQ(a.get(2), 2);
uint16_t* data = a.data<uint16_t>();
    template<typename T>
    T* data() {
        return nullptr;
    }