将常量值传递给模板

Passing constant value to template

我正在使用具有两个模板化参数的模板class

itk::Image<PIXELTYPE,DVALUE>

在读取图像时,我将获得有关图像类型和尺寸的信息。因为有 11 个可能的类型值和 3 个维度值 (2,3,4) 每次我读取图像并且必须应用我正在执行的操作如下:

std::string type = IOBase->GetComponentTypeAsString(IOBase->GetComponentType());
const unsigned int dim = IOBase->GetNumberOfDimensions();

if(dim ==3)
{
    if(type == "unsigned_char")
    {
        typedef itk::Image<unsigned char,3> ImageType;
        //apply operation
    }
    else if(type == "char")
    {
        typedef itk::Image< char,3> ImageType;
        //apply operation

    }
    else if(type ==....so on 
}

然后我必须再次为 dim=4dim ==2 执行此操作 它增加了太多代码。所以我试图通过将其值设置为 :

来避免 if else 检查暗淡
std::string type = IOBase->GetComponentTypeAsString(IOBase->GetComponentType());
const unsigned int dim = IOBase->GetNumberOfDimensions();

if(type == "unsigned_char")
{
            typedef itk::Image<unsigned char,3> ImageType;

我有以下情况:

  const unsigned int dimension = 3;
  itk::Image<unsigned char, dimension > image;

在执行时,我必须找到类型和尺寸,然后才能创建图像。当我 运行 上面的代码工作时。但是当我尝试通过以下方式执行此操作时:

const unsigned int dimension = FunctionGetDimension();
itk::Image<unsigned char, dimension > image;

即使我将 FunctionGetDimension() 的 return 值设为 const,它也不起作用。有什么办法吗?

模板参数应该在编译时已知,不可能在 运行 时指定它们。即使您的 dim 是常量,它在编译时也是未知的。

因此无论如何您需要一些或多或少的手工逻辑来创建您需要的 Image 对象。一个常见的方法是创建一个工厂。

我假设您已经拥有最简单的工厂类型 — if/else if/else if... 子句链,每个子句返回一个不同类型的对象。你最好将它设置为一个单独的函数,如下所示:

// I assume that itk::Image subclasses a non-template BasicImage
// if this is not the case, you will need some kind of a wrapper
// you should also return unique_ptr or its friends instead of raw pointer
BasicImage* createImage(int dim, std::string type) {
    if (dim == 3) {
        if (type == "unsigned_char")
            return new itk::Image<unsigned char, 3>();
        else if...
    } else if...
}

还有更高级的技术:除了硬编码 if/else 链,您可以将其设为 class 并保留 std::map 创建所需对象的函数,并让对象自己注册到它,请参阅 "Factory Pattern" and "Factory Pattern in C++"。这不会节省太多代码,因为您仍然会有注册每个 class 的代码,但是您可以将此注册移到更好的地方并获得更多优势。

但是,我不会把事情复杂化。只要你了解工厂是如何工作的,你就可以从一个带有硬编码 if/else 链的简单工厂开始,然后,如果需要,切换到使用 map 和注册的工厂而不改变工厂的客户端界面。就是提前想到了这个界面

相反,如果您的模板确实有很多变体,则不仅需要使用 std::map 实现,还需要让编译器为您处理注册。为此,您可能需要查看 "Subscribing Template Classes with Object Factories in C++",它描述了一个与您的案例非常相似的案例,并添加了一些更高级的方法。