模板更改一小部分时共享模板函数的常用功能

时间:2016-09-25 05:40:38

标签: c++ templates

我的项目在模板方面有几个尴尬的位置。我知道我的用法略微不标准,但作为基本利益的尴尬(主要是展开一堆循环)。 AKA请不要回答“哦,你不应该使用模板”。所涉及的尴尬在经验上已被证明有超过10倍的加速......

以下模板使用enum class SomeThing : uint8_t。有一个

template <SomeThing ST>
struct projection_functor {
    static constexpr unsigned WIDTH  = 640u;/// *** only in
    static constexpr unsigned HEIGHT = 480u;/// *** specializations...
    void toXYZ(...);
    ...
};

保证enum class SomeThing的每个可能值都有专门的版本。此外,非专业版本实际上并不提供WIDTHHEIGHT,只提供专业化(这是我的编译时保证措施)。

我想要做的是使用这些闭包定义一个函数:

template <SomeThing ST>
void forEachXYZ(...params...) {
    if(ST == SomeThing::FIRST)
        using proj = projection_functor<SomeThing::FIRST>;
    else if(ST == SomeThing::SECOND)
        using proj = projection_functor<SomeThing::SECOND>;
    else
        throw std::runtime_error("Unsupported...");

    for(unsigned i = 0; i < proj::WIDTH * proj::HEIGHT; ++i) {
        // ... setup ...
        proj pf;
        pf.toXYZ(...);
    }
}

这不能编译,但我认为问题proj在每种情况下都没有正式定义。这是一个非常丑陋但功能性的解决方案,我想保留在forEachXYZ

#define THIS_UGLY_MACRO() \
    for(unsigned int i = 0; n < proj::WIDTH * proj::HEIGHT; ++i) { \
        /* ... setup ... */ \
        proj pf; \
        pf.toXYZ(...); \
    }

现在我可以打电话了

template <SomeThing ST>
void forEachXYZ(...params...) {
    if(ST == SomeThing::FIRST) {
        using proj = projection_functor<SomeThing::FIRST>;
        THIS_UGLY_MACRO();
    }
    else if(ST == SomeThing::SECOND) {
        using proj = projection_functor<SomeThing::SECOND>;
        THIS_UGLY_MACRO();
    }
    else
        throw std::runtime_error("Unsupported...");
}

这显然有效,因为它的范围是从模板参数比较中评估的if语句。

这是唯一的解决方案,还是有更好的方法可以根据模板参数告知循环proj实际是什么?

我认为编写一个辅助函数可以完成,但这更高级别“我能以这种方式实际使用模板做什么”这个问题。

感谢您的任何建议:)

1 个答案:

答案 0 :(得分:1)

您可以定义模板而不是宏:

template <class Projection>
void projectXYZ(...params...) {
    for(unsigned int i = 0; n < proj::WIDTH * proj::HEIGHT; ++i) {
        /* ... setup ... */
        Projection pf;
        pf.toXYZ(...);
    }
}

然后叫它:

template <SomeThing ST>
void forEachXYZ(...params...) {
    if(ST == SomeThing::FIRST) {
        projectXYZ<projection_functor<SomeThing::FIRST>>(std::move(param), ...);
    }
    else if(ST == SomeThing::SECOND) {
        projectXYZ<projection_functor<SomeThing::SECOND>>(std::move(param), ...);
    }
    else {
        throw std::runtime_error("Unsupported...");
    }
}