2017-06-17 88 views
0

我正在使用HDF5库,并试图编写一个模板函数来支持具有不同数据类型的I/O。目标只是为了减少和简化复制和粘贴,我需要做的是创建所有不同的功能。如何在C++中基于函数模板类型应用不同的#define?

在HDF5库这是写调用(documentation here)格式:

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,其中i为每个类型的特专门的模板功能。
  2. 巨人if语句
+1

'#define'是一个预处理指令;在编译器甚至标记程序之前对它进行评估;所以我没有机会以某种方式根据稍后编译步骤中评估的类型选择一组不同的'#define'语句。但我不确定这是否是您的问题。 –

回答

1

所以,当我本来下投票,因为这是我想选择一个预处理器声明。这是我制定的解决方案。

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

#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()放置在正确的位置。这将执行特定数据块的导入。它使用了一个模板,所以我可以轻松地使用它在我的代码中创建函数,而无需重新使用它。通过不定义一般模板和使用模板专业化,我可以将案例限制在我知道的一般人们将在图书馆中使用的情况中。如果需要一个新案例,我可以构建一个。

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

相关问题