C++ - Return 具有未知模板参数的模板
C++ - Return a template with unknown template argument
我想从可以容纳多种不同类型数据的文件类型中加载图像:像素可以编码为 float
s、double
s、unsigned char
s、 char
s(类似于 TIF 文件)。加载后我对图像数据所做的所有处理取决于将要加载的数据类型。我已经有一个函数可以在给定文件路径和数据类型的情况下从处理我的文件类型的 C 中的外部库加载适当的数据:
/* loads image with pixels of type T in a 1D array (fine for my use case) */
template <typename T> std::vector<T> loadImg(std::string path) {
std::vector<T> imgData;
file imgFile = libOpen(path);
imgData.resize(imgFile.height * imgFile.width);
libReadImg(imgFile, imgData.data());
return imgData;
}
我想要的是有一个 'generic' 加载程序,我的程序的用户可以从中指定他们想要的任何类型的支持文件,它会加载它们并定义正确的模板类型return,在运行时:
/* load the user's selected files : */
template <> /*what do I put here in template argument ?*/
std::vector</*and here ?*/> loadAnyImg(std::string path) {
file imgFile = openFile(...);
if (imgFile.type == int) {
return loadImg<int>(path);
}
if (imgFile.type == unsigned char) {
return loadImg<unsigned char>(path);
}
/* ... */
}
有没有办法在 C++ 中做这样的事情?在那之前我已经处理了很多模板,但在这个特定的用例中没有。
快速编辑:当然,我也可以将所有加载的数据转换为具有 min/max 边界的内部格式(即将所有像素数据转换为具有 min/max 边界的 double
除它之外的类型)。但我想尽可能保持数据不变
Return 像这样:
std::variant< std::vector<int>, std::vector<unsigned char>, std::vector<double> >
这不是模板,因为调用哪个模板是在编译时确定的。
调用者可以通过std::visit
获取哪个向量,并获取数据的编译时实例。
支持的类型必须在编译时枚举,因为每种类型都会生成新的代码来处理它。
Variant 是一个“求和类型”。它可以是它包含的任何一种类型。
(如果有异常,在极少数情况下它可能毫无价值;只有当您 运行 超出地址 space 时,基本类型的向量变体才会处于该状态计算机同时对变体进行一些特定的操作;如果你只是在变体之外制作向量并移入其中,而不是 copy/assign 变体,那应该是一个完全不可能达到的状态。
调用者可以这样取出具体的矢量数据:
bool bWorked = std::visit([&](auto& vec){
// here `vec` is a vector of concrete type
return true;
}, loaded_data);
现在,如果您真的想要 any 类型(而您不想要,相信我),那么您可以 return 一个 std::any
。但是调用者必须知道 any
中的确切类型才能与之交互(超出 copy/move)。 std::any
通常是个坏主意。
我想从可以容纳多种不同类型数据的文件类型中加载图像:像素可以编码为 float
s、double
s、unsigned char
s、 char
s(类似于 TIF 文件)。加载后我对图像数据所做的所有处理取决于将要加载的数据类型。我已经有一个函数可以在给定文件路径和数据类型的情况下从处理我的文件类型的 C 中的外部库加载适当的数据:
/* loads image with pixels of type T in a 1D array (fine for my use case) */
template <typename T> std::vector<T> loadImg(std::string path) {
std::vector<T> imgData;
file imgFile = libOpen(path);
imgData.resize(imgFile.height * imgFile.width);
libReadImg(imgFile, imgData.data());
return imgData;
}
我想要的是有一个 'generic' 加载程序,我的程序的用户可以从中指定他们想要的任何类型的支持文件,它会加载它们并定义正确的模板类型return,在运行时:
/* load the user's selected files : */
template <> /*what do I put here in template argument ?*/
std::vector</*and here ?*/> loadAnyImg(std::string path) {
file imgFile = openFile(...);
if (imgFile.type == int) {
return loadImg<int>(path);
}
if (imgFile.type == unsigned char) {
return loadImg<unsigned char>(path);
}
/* ... */
}
有没有办法在 C++ 中做这样的事情?在那之前我已经处理了很多模板,但在这个特定的用例中没有。
快速编辑:当然,我也可以将所有加载的数据转换为具有 min/max 边界的内部格式(即将所有像素数据转换为具有 min/max 边界的 double
除它之外的类型)。但我想尽可能保持数据不变
Return 像这样:
std::variant< std::vector<int>, std::vector<unsigned char>, std::vector<double> >
这不是模板,因为调用哪个模板是在编译时确定的。
调用者可以通过std::visit
获取哪个向量,并获取数据的编译时实例。
支持的类型必须在编译时枚举,因为每种类型都会生成新的代码来处理它。
Variant 是一个“求和类型”。它可以是它包含的任何一种类型。
(如果有异常,在极少数情况下它可能毫无价值;只有当您 运行 超出地址 space 时,基本类型的向量变体才会处于该状态计算机同时对变体进行一些特定的操作;如果你只是在变体之外制作向量并移入其中,而不是 copy/assign 变体,那应该是一个完全不可能达到的状态。
调用者可以这样取出具体的矢量数据:
bool bWorked = std::visit([&](auto& vec){
// here `vec` is a vector of concrete type
return true;
}, loaded_data);
现在,如果您真的想要 any 类型(而您不想要,相信我),那么您可以 return 一个 std::any
。但是调用者必须知道 any
中的确切类型才能与之交互(超出 copy/move)。 std::any
通常是个坏主意。