在@bolov 的回答的基础上,可以i
通过更改在不是常量时使用任意调度算法:
constexpr auto execute(int i)
{
(execute_if<Is>(i), ...);
}
至:
constexpr auto execute(unsigned i)
{
(execute_if<Is>(i), ...);
}
然后添加:
constexpr auto execute (int& i)
{
// Add arbitrary dispatch mechanism here
}
完整的示例,与 C++11 兼容并在不是常量时使用相当笨重的std::map
(最坏情况复杂度 log n) (我放弃了这些东西以使 C++11 中的生活更轻松):i
constexpr
#include <map>
#include <iostream>
std::map <int, void (*) ()> map;
template <int i> void f ();
template <> void f <1> () { std::cout << "f1\n"; }
template <> void f <2> () { std::cout << "f2\n"; }
template <> void f <3> () { std::cout << "f3\n"; }
template <> void f <4> () { std::cout << "f4\n"; }
template <> void f <5> () { std::cout << "f5\n"; }
template <int ... Is>
struct Dispatcher
{
template <int first> void execute_if (int i)
{
if (first == i)
{
std::cout << "Execute f" << i << " via template\n";
f <first> ();
}
}
template <int first, int second, int... rest> void execute_if (int i)
{
if (first == i)
{
std::cout << "Execute f" << i << " via template\n";
f <first> ();
}
else
execute_if <second, rest...> (i);
}
void execute (unsigned i)
{
execute_if <Is...> (i);
}
void execute (int& i)
{
std::cout << "Execute f" << i << " via map\n";
map.at (i) ();
}
};
int main()
{
map [1] = f <1>;
map [2] = f <2>;
map [3] = f <3>;
map [4] = f <4>;
map [5] = f <5>;
Dispatcher <1, 2, 4> dispatcher;
dispatcher.execute (2);
int i = 4;
dispatcher.execute (i);
}
输出:
Execute f2 via template
f2
Execute f4 via map
f4
现场演示
编辑:根据 OP 的要求,这是一个使用二进制搜索而不是std::map
. 关键是在构造函数中构建要搜索的数组Dispatcher
。
#include <vector>
#include <iostream>
template <int i> void f ();
template <> void f <1> () { std::cout << "f1\n"; }
template <> void f <2> () { std::cout << "f2\n"; }
template <> void f <3> () { std::cout << "f3\n"; }
template <> void f <4> () { std::cout << "f4\n"; }
template <> void f <5> () { std::cout << "f5\n"; }
using ve = std::pair <int, void (*) ()>;
template <int ... Is>
struct Dispatcher
{
template <int first> void execute_if (int i)
{
if (first == i)
{
std::cout << "Execute f" << i << " via template\n";
f <first> ();
}
}
template <int first, int second, int... rest> void execute_if (int i)
{
if (first == i)
{
std::cout << "Execute f" << i << " via template\n";
f <first> ();
}
else
execute_if <second, rest...> (i);
}
void execute (unsigned i)
{
execute_if <Is...> (i);
}
void execute (int& i)
{
std::cout << "Execute f" << i << " via binary search\n";
auto lb = lower_bound (indexes.begin (), indexes.end (), ve (i, nullptr),
[] (ve p1, ve p2) { return p1.first < p2.first; });
if (lb != indexes.end () && lb->first == i)
lb->second ();
}
template <int first> void append_index ()
{
indexes.emplace_back (ve (first, f <first>));
}
template <int first, int second, int... rest> void append_index ()
{
append_index <first> ();
append_index <second, rest...> ();
}
Dispatcher ()
{
append_index <Is...> ();
}
private:
std::vector <ve> indexes;
};
int main()
{
Dispatcher <1, 2, 4> dispatcher;
dispatcher.execute (2);
int i = 4;
dispatcher.execute (i);
}
现场演示