如何在C++中根据函数模板类型应用不同的 #define?

How do I apply a different #define based on function template type in C++?

本文关键字:应用 #define 类型 函数模板 C++      更新时间:2023-10-16

我正在使用HDF5库,并正在尝试编写一个模板函数来支持不同数据类型的I/O。目标只是减少和简化我需要做的复制和粘贴来创建所有不同的功能。

在 HDF5 库中,这是写入调用的格式(此处为文档):

H5Dwrite(hid_t dataset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t xfer_plist_id, const void * buf )

其中许多参数是在我的函数中生成的,或者作为函数参数传递。唯一的问题是mem_type_id,它被定义为库头文件中的一系列#define子句。

我可以使用一些技巧来根据模板类型更改它吗?我宁愿避免到处都是std::typeid(T)的巨大条件语句。编译时,代码已经很大了,因此避免存储不必要的条件所需的字节似乎是可取的。我应该实现 40 多种类型,以便在将来的项目中保留此泛型。如果无论如何都可以限制我的模板允许我未定义的类型,这可能会让我将工作减少到最低限度。

我可能的解决方案包括:

  1. 创建返回 HDF5 类型的专用模板函数 id,其中我对每种类型都有专门的介绍。
  2. 巨人如果语句

因此,虽然我最初被否决了,因为它是我试图选择的预处理器语句。这是我制定的解决方案。

我有两个头文件,第一个是这个

#pragma once
#include "hdf5.h"
template <typename T> hid_t  HdfType();
template<> hid_t  HdfType<short>() { return H5T_NATIVE_SHORT; }
template<> hid_t  HdfType<unsigned short>()  { return H5T_NATIVE_USHORT; }
template<> hid_t  HdfType<int> () { return H5T_NATIVE_INT;}
template<> hid_t  HdfType<unsigned int> () { return H5T_NATIVE_UINT; }
template<> hid_t  HdfType<long> () { return H5T_NATIVE_LONG; }
template<> hid_t  HdfType<unsigned long> () { return H5T_NATIVE_ULONG; }
template<> hid_t  HdfType<long long> () { return H5T_NATIVE_LLONG; }
template<> hid_t  HdfType<unsigned long long> () { return H5T_NATIVE_ULLONG; }
template<> hid_t  HdfType<char> () { return H5T_NATIVE_CHAR; }
template<> hid_t  HdfType<unsigned char> () { return H5T_NATIVE_UCHAR; }
template<> hid_t  HdfType<signed char> () { return H5T_NATIVE_SCHAR; }
template<> hid_t  HdfType<float> () { return H5T_NATIVE_FLOAT; }
template<> hid_t  HdfType<double> () { return H5T_NATIVE_DOUBLE; }
template<> hid_t  HdfType<long double> () { return H5T_NATIVE_LDOUBLE; }

此文件从#define返回预定义句柄编号。第二个文件包含以下内容

#pragma once
#include "hdf5.h"
#include "HdfTypeTemplate.h"
#include <vector>
template <typename T, int dims=1, int numColumns =1>
void CollectiveHdfBlockImport(hid_t datasetId, long long startRowIndex, long long numRowsToImport, std::vector<T>& data)
{
data.resize(numRowsToImport * numColumns + 10);
hid_t dtplId = CreateCollectiveDataTransferPropertiesList();
hid_t dataspaceId = H5Dget_space(datasetId);
hsize_t start[2] = { 0 }, count[2] = { 0 }, strideAndBlocks[2] = { 1,1 };
count[0] = numRowsToImport;
count[1] = numColumns;
start[0] = startRowIndex;
start[1] = 0;
hid_t memspaceId = H5Screate_simple(dims, count, NULL);
H5Sselect_hyperslab(dataspaceId, H5S_SELECT_SET, start, strideAndBlocks, count, strideAndBlocks);
H5Dread(datasetId, HdfType<T>(), memspaceId, dataspaceId, dtplId, data.data());
H5Sclose(dataspaceId);
H5Sclose(memspaceId);
H5Pclose(dtplId);
}

您会看到 HDFType() 被放置在正确的位置。这将执行特定数据块的导入。它利用了一个模板,所以我可以轻松地使用它在我的代码中创建函数,而无需重写它。通过不定义通用模板并使用模板专用化,我可以将案例限制为我知道人们将在库中使用的一般情况。如果需要一个新的案例,我可以构建一个。

如果有人有更好的解决方案,请发布它们。