[英]C++ Call functions based on enum values
I have this code我有这个代码
class Foo {
private:
enum class Heuristic {
ONE,
TWO,
THREE
};
Heuristic h;
void select();
};
void Foo::select() {
if (h == Heuristic::ONE)
selectONE();
else if (h == Heuristic::TWO)
selectTWO();
else
selectTHREE();
}
void selectONE() {};
void selectTWO() {};
void selectTHREE() {};
Based on the value of heuristic
I want to call a specific function in select()
.基于
heuristic
的值,我想在select()
中调用特定的 function 。 I don't know the value of heuristic
at compile time, as it depends on user input.我不知道
heuristic
在编译时的价值,因为它取决于用户输入。 To avoid the conditional check in select()
I would like to use templates.为了避免
select()
中的条件检查,我想使用模板。 How can I accomplish this?我怎样才能做到这一点?
As it depends on runtime values there is no way to get rid of some sort of runtime checks.由于它取决于运行时值,因此无法摆脱某种运行时检查。 Which are either done by you with
if
, switch
, … or by a container like std::map
, std::unordered_map
您可以使用
if
、 switch
…… 或者像std::map
、 std::unordered_map
这样的容器来完成这些操作
Due to that, your concern there should be readability and maintainability.因此,您关心的应该是可读性和可维护性。
I would - like already suggested in a comment - use switch
instead of if
, but not because the compiler can optimize it better (IMHO the compiler will be able to generate the same code for both), but to allow the static analyzer to warn you about not used enums.我想 - 就像评论中已经建议的那样 - 使用
switch
而不是if
,但不是因为编译器可以更好地优化它(恕我直言,编译器将能够为两者生成相同的代码),而是允许 static 分析器警告你关于未使用的枚举。
If the question is about performance concerns, then this should only be a problem if you call these functions at a high frequency.如果问题是关于性能问题,那么只有在高频调用这些函数时才会出现问题。 So if this is the case you could create a template-based entry point to your task, to which you pass the function as template argument based on the user selection:
因此,如果是这种情况,您可以为您的任务创建一个基于模板的入口点,根据用户选择将 function 作为模板参数传递给该入口点:
template<auto SelectedHeuristic>
void Foo::task() {
for( /* … */ ) {
SelectedHeuristic();
}
}
void Foo::select() {
switch(h) {
case Heuristic::ONE:
Foo::task<selectONE>();
break;
case Heuristic::TWO:
Foo::task<selectTWO>();
break;
case Heuristic::THREE:
Foo::task<selectTHREE>();
break;
}
}
void selectONE() {};
void selectTWO() {};
void selectTHREE() {};
To avoid the conditional check in
select()
[...]为了避免
select()
中的条件检查 [...]
A simple way to avoid all conditional checks (hidden or otherwise) in select()
could be to create an array of pointers to your functions.在
select()
中避免所有条件检查(隐藏或其他)的一种简单方法是创建一个指向函数的指针数组。 You then look the function up by using its current Heuristic
value (which must start at 0 and not have any gaps).然后,您使用 function 的当前
Heuristic
值(必须从 0 开始并且没有任何间隙)向上查看。 If the Heuristic
value changes rarely, you can even move the lookup out of select()
completely.如果
Heuristic
值很少更改,您甚至可以将查找完全移出select()
。
Example:例子:
##include <iostream>
void selectONE() { std::cout << "one\n"; };
void selectTWO() { std::cout << "two\n"; };
void selectTHREE() { std::cout << "three\n"; };
using func_ptr_t = void(*)(); // the signature of your functions
class Foo {
public:
enum class Heuristic {
ONE,
TWO,
THREE
};
void set_heuristic(Heuristic); // a function to do the lookup
void select();
private:
Heuristic h;
func_ptr_t current_func; // a pointer to the selected function
};
void Foo::set_heuristic(Heuristic value) {
// a simple map from Heuristic value to function pointer
static const func_ptr_t funcmap[] = {
&selectONE,
&selectTWO,
&selectTHREE,
};
h = value; // perhaps not needed?
// look up the function pointer based on "h"
current_func = funcmap[static_cast<unsigned>(h)];
}
void Foo::select() {
// a pretty fast callsite:
current_func();
}
int main() {
Foo bar;
bar.set_heuristic(Foo::Heuristic::ONE);
bar.select(); // prints "one"
}
define a map<Heuristic, lambdas>
where the lambdas are defined as void and taking no parameters定义一个
map<Heuristic, lambdas>
其中 lambdas 被定义为 void 并且不带参数
void f()
then take the user input and get the value of that input key and trigger the lambda然后获取用户输入并获取该输入键的值并触发 lambda
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.