首页 > 解决方案 > 元程序在运行时使用枚举值作为模板函数的模板参数

问题描述

假设我有这个代码:

// the enumerator
enum class my_enum {
    ONE,
    TWO,
    THREE
};

// the function
template <my_enum E>
int foo() {
    return 0;
}

// a specialization
template<>
int foo<my_enum::TWO>() {
    return 1;
}

我想编写一个bar专门foo针对 的每个元素的函数my_enum,并在运行时根据 的参数的值调用其中一个函数bar。最简单的解决方案是编写一个开关并手动添加所有案例:

int bar(my_enum value) {
    switch (value) {
    using m = my_enum;
    case m::ONE:
        return foo<m::ONE>();
    case my_enum::TWO:
        return foo<m::TWO>();
    case my_enum::THREE:
        return foo<m::THREE>();
    }
}

使用一些额外的技巧来处理添加开关的默认值的意外值。不幸的是,对于非常长的枚举器,这种解决方案会带来非常长且冗余的代码,这很难维护。

是否有任何元编程解决方案来简化此代码,例如使用 Boost Hana 或 Boost MPL?

标签: c++templatesenumsmetaprogramming

解决方案


如果枚举值如您的示例所示,从零开始并且连续...给定一个辅助函数,如下所示

template <std::size_t ... Is>
std::array<int(*)(void), sizeof...(Is)>
    getFuncArray (std::index_sequence<Is...>)
 { return {{ &foo<static_cast<my_enum>(Is)>... }}; }

您可以在 中添加bar()static组函数并根据输入调用正确的函数。

我是说

int bar (my_enum value)
 {
   static auto const arrF
      = getFuncArray(std::make_index_sequence<
                        1u+static_cast<std::size_t>(my_enum::THREE)>{});

   return arrF[static_cast<std::size_t>(value)]();
 }

推荐阅读