0

我想从可以保存许多不同类型数据的文件类型中加载图像:像素可以编码为floats、doubles、unsigned chars、chars(类似于 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;
}

我想要的是有一个“通用”加载器,我的程序的用户可以从中指定他们想要的任何类型的支持文件,它会加载它们并在运行时定义要返回的正确类型的模板:

/* 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++ 中做这样的事情?在那之前我已经处理了很多模板,但在这个特定的用例中没有。

快速编辑:当然,我还可以将所有加载的数据转换为具有最小/最大界限的内部格式(即,将所有像素数据转换为double具有除此之外的类型的最小/最大界限)。但我想尽可能保持数据不变

4

1 回答 1

4

返回如下内容:

std::variant< std::vector<int>, std::vector<unsigned char>, std::vector<double> >

这不是模板,因为您调用的模板是在编译时确定的。

调用者可以通过执行 a 来获取哪个向量,std::visit并获取数据的编译时实例。

支持的类型必须在编译时枚举,因为为每种类型生成新代码来处理它。


Variant 是一种“求和类型”。它可以是它包含的任何一种类型。

(如果有例外,它在极少数情况下可能毫无价值;只有当您在对变体执行一些特定操作时计算机上的地址空间用完时,原始类型向量的变体才会处于该状态;如果您只在变体之外制作向量并移入其中,并且从不复制/分配变体,这应该是完全不可能达到的状态)。

调用者可以像这样获取特定的向量数据:

bool bWorked = std::visit([&](auto& vec){
  // here `vec` is a vector of concrete type
  return true;
}, loaded_data);

现在,如果你真的想要任何类型(而你不需要,相信我),那么你可以只返回一个std::any. 但是调用者必须知道确切的类型any才能与之交互(除了复制/移动)。 std::any通常是个坏主意。

于 2020-11-24T17:54:54.347 回答