英文:
Is there any better way than using a switch/case to execute code based on a numerical value?
问题
我有这段C++代码,根据变量的值执行任意算术操作:
int foo = {value};
float execute(float input_1, float input_2) {
switch (foo) {
case 1:
return (input_1 + input_2);
case 2:
return (input_1 - input_2);
case 3:
return (input_1 * input_2);
case 4:
return (input_1 / input_2);
default:
return 0;
}
}
这段代码片段相对较简单 - 如果只是这么简单的话,我就不会在这里发帖了。
我将会有大约50个不同的case
用于foo
的值,这似乎有点笨拙,只是硬编码每个值,然后逐个检查foo
变量是否与之前的每个值相等;特别是因为它只是将递增的值映射到一个运算符。是否有更好的方法 - 更干净的代码或更快的方法?
英文:
I have this code in C++ that executes arbitrary arithmetic based on the value of a variable:
int foo = {value};
float execute(float input_1, float input_2) {
switch (foo) {
case 1:
return (input_1 + input_2);
case 2:
return (input_1 - input_2);
case 3:
return (input_1 * input_2);
case 4:
return (input_1 / input_2);
default:
return 0;
}
}
This code snippet is a pretty big understatement - I wouldn't be posting here if it was this simple.
I'll have around 50 different case
s for the foo
value, which seems a bit clunky to just hard-code every value and then check the foo
variable against every previous value one-by-one; especially since it's just mapping an incrementing value to an operator. Some sort of list or array that only executes the included code if the index is called, or something like that.
Is there any better way - that being cleaner code or speed?
答案1
得分: 4
以下是您提供的代码的翻译部分:
考虑一个将foo操作映射到函数指针、成员函数或lambda的哈希表。
经典的C跳转表:
#include <unordered_map>
#include <functional>
using namespace std;
typedef float (*OpFn)(float x, float y);
float add(float x, float y) { return x + y; }
float sub(float x, float y) { return x - y; }
float mult(float x, float y) { return x * y; }
float div(float x, float y) { return x / y; }
typedef float (*OperationFn)(float, float);
extern int foo;
float execute(float input_1, float input_2) {
static std::unordered_map<int, OperationFn> optable = {
{1, add},
{2, sub},
{3, mult},
{4, div}
};
auto itor = optable.find(foo);
if (itor != optable.end()) {
return itor->second(input_1, input_2);
}
return 0;
}
C++使用成员函数指针的跳转表:
class Foo {
Foo() {
optable = {
{1, &Foo::add},
{2, &Foo::sub},
{3, &Foo::mult},
{4, &Foo::div}
};
}
int foo;
float add(float x, float y) { return x + y; }
float sub(float x, float y) { return x - y; }
float mult(float x, float y) { return x * y; }
float div(float x, float y) { return x / y; }
typedef float (Foo::* FooOp)(float, float);
std::unordered_map<int, FooOp> optable;
float execute(float input1, float input2) {
auto itor = optable.find(foo);
if (itor != optable.end()) {
auto& fn = itor->second;
(this->*fn)(input1, input2);
}
return 0;
};
};
或映射到lambda函数:
float execute(float input_1, float input_2) {
static std::unordered_map<int, std::function<float(float, float)>> optable = {
{1, [](float x, float y) {return x + y; }},
{2, [](float x, float y) {return x - y; }},
{3, [](float x, float y) {return x * y; }},
{4, [](float x, float y) {return x / y; }},
};
auto itor = optable.find(foo);
if (itor != optable.end()) {
return itor->second(input_1, input_2);
}
return 0;
}
在您提供的所有情景中,您不必在函数内联初始化optable。可以在其他地方初始化并存储,例如作为全局变量或类的成员。
英文:
Consider a hash table that maps the foo operation to a function pointer, member function, or lambda.
Classic C jump table:
#include <unordered_map>
#include <functional>
using namespace std;
typedef float (*OpFn)(float x, float y);
float add(float x, float y) { return x + y; }
float sub(float x, float y) { return x - y; }
float mult(float x, float y) { return x * y; }
float div(float x, float y) { return x / y; }
typedef float (*OperationFn)(float, float);
extern int foo;
float execute(float input_1, float input_2) {
static std::unordered_map<int, OperationFn> optable = {
{1, add},
{2, sub},
{3, mult},
{4, div}
};
auto itor = optable.find(foo);
if (itor != optable.end()) {
return itor->second(input_1, input_2);
}
return 0;
}
C++ jump table using pointer to member functions:
class Foo {
Foo() {
optable = {
{1, &Foo::add},
{2, &Foo::sub},
{3, &Foo::mult},
{4, &Foo::div}
};
}
int foo;
float add(float x, float y) { return x + y; }
float sub(float x, float y) { return x - y; }
float mult(float x, float y) { return x * y; }
float div(float x, float y) { return x / y; }
typedef float (Foo::* FooOp)(float, float);
std::unordered_map<int, FooOp> optable;
float execute(float input1, float input2) {
auto itor = optable.find(foo);
if (itor != optable.end()) {
auto& fn = itor->second;
(this->*fn)(input1, input2);
}
return 0;
};
};
Or map to lambda functions:
float execute(float input_1, float input_2) {
static std::unordered_map<int, std::function<float(float, float)>> optable = {
{1, [](float x, float y) {return x + y; }},
{2, [](float x, float y) {return x - y; }},
{3, [](float x, float y) {return x * y; }},
{4, [](float x, float y) {return x / y; }},
};
auto itor = optable.find(foo);
if (itor != optable.end()) {
return itor->second(input_1, input_2);
}
return 0;
}
In all of your above scenarios you don't have to inline initialize the optable within the function. That can be initialized and stored elsewhere such as a global variable or as a member of a class.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论