简体   繁体   English

C++ 基于枚举值调用函数

[英]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您可以使用ifswitch …… 或者像std::mapstd::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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM