首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++模板类:在运行时给出的模板参数,如何避免重复大开关的情况?

C++模板类:在运行时给出的模板参数,如何避免重复大开关的情况?
EN

Stack Overflow用户
提问于 2018-08-12 13:22:57
回答 1查看 119关注 0票数 3

我目前正在开发一个图像处理应用程序,主要基于C++和ITK。

1.形势

我有来自同一个基类的节点类(例如FlipFilter)。节点获取具有image_ptr和所有元信息( ImagePixelType (例如RGB、RGBA、标量)和ComponentType (例如浮点、int)的维数的结构。节点必须基于这些ITK-Filter实例化一个Meta-Informations,该Meta-Informations可以在每个输入图像上进行更改。

2.问题

这些ITK-Filters需要ImageType (例如RGB和ComponentType UCHAR)作为模板参数。模板类必须在编译时实例化.我的节点正在运行时获取具有其类型的映像。因此,我必须为每个节点创建过滤器的所有排列,然后使用适当的实例化。

3.我目前的解决方案

此结构包含指向实际图像的所有meta-information + smart-pointer。我使用图像的一个基本指针,因为图像本身也是一个模板(稍后我将向下转换)。

代码语言:javascript
复制
struct ImageData
{
    short NumberOfDimensions;
    itk::ImageIOBase::IOComponentType ComponentType;
    itk::ImageIOBase::IOPixelType PixelType;
    itk::DataObject::Pointer Image;
    ImageData() {}
    ~ImageData() {}
};

这是我的节点的更新函数。它应该创建过滤器,在图像上执行它。

代码语言:javascript
复制
void LitkFlipImageFilter::update()
{
    if (Input1 == nullptr)
        throw(std::runtime_error("Input1 not set"));


    Input1->update();

    ImageData Input1Data = Input1->getOutput();

    switch (Input1Data.PixelType)
    {
        default:
        {
            throw std::runtime_error("Type not Supported");
            break;
        }
        case itk::ImageIOBase::RGB:
        {
            switch (Input1Data.ComponentType)
            {
                default:
                {
                    throw std::runtime_error("Type not Supported");
                    break;
                }
                case itk::ImageIOBase::IOComponentType::UCHAR:
                {
                    using PixelType = itk::RGBPixel< unsigned char >;
                    using ImageType = itk::Image < PixelType, 2 >;
                    itk::FlipImageFilter<ImageType>::Pointer filter = itk::FlipImageFilter<ImageType>::New();
                    //do stuff

                    break;
                }
            break;
            }
        }
    }
}

4.我的解决方案的问题

它可以工作,但会产生大量重复代码和大量嵌套的开关情况。你知道如何更好地解决这个问题吗?

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2018-08-12 15:06:38

您想要的高级别处理是:

代码语言:javascript
复制
template <typename PixelType>
void do_stuff()
{
    using ImageType = Image < PixelType, 2 >;
    ...do stuff...
}

您可以创建一个详细但可重用的版本(通过更改要分派到的"Fn“代码)转换代码的版本:

代码语言:javascript
复制
template <typename Fn>
void dispatch(PixelType pt, ComponentTypeId ct, Fn fn) {
    switch (pt)
    {
      case RGB:
        switch (ct) {
          case Uint8_t: fn(RGBPixel<uint8_t>{}); return;
          case Float:   fn(RGBPixel<float>{}); return;
        };
      case RGBA:
        switch (ct) {
          case Uint8_t: fn(RGBAPixel<uint8_t>{}); return;
          case Float:   fn(RGBAPixel<float>{}); return;
        };
      case Scalar:
        switch (ct) {
          case Uint8_t: fn(ScalarPixel<uint8_t>{}); return;
          case Float:   fn(ScalarPixel<float>{}); return;
        };
    }
}

那么,就这样说吧:

代码语言:javascript
复制
dispatch(runtime_pixel_type, runtime_component_type, 
         [](auto pt) { do_stuff<decltype(pt)>(); });

备注:

  • 对lambda使用默认构造的"XXXPixel“参数是丑陋的-- C++2a应该引入适当的模板化lambdas (?!)把这个清理干净。
  • 您可以链接几个基于一个运行时变量的“分派”函数,以避免开关用例的倍增性爆炸;这样的函数扩展得更好,但在这里太费劲了,您必须使用PixelType作为模板。
  • 您可以在default: throw后面添加break (或return),因为它们永远不会返回到下面的代码行
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51809217

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档