有没有比使用 switch/case 根据数值执行代码更好的方法?

huangapple go评论77阅读模式
英文:

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 cases 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 &lt;unordered_map&gt;
#include &lt;functional&gt;
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&lt;int, OperationFn&gt; optable = {
		{1, add},
		{2, sub},
		{3, mult},
		{4, div}
	};

	auto itor = optable.find(foo);
	if (itor != optable.end()) {
		return itor-&gt;second(input_1, input_2);
	}
	return 0;
}

C++ jump table using pointer to member functions:

class Foo {

	Foo() {
		optable = {
			{1, &amp;Foo::add},
			{2, &amp;Foo::sub},
			{3, &amp;Foo::mult},
			{4, &amp;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&lt;int, FooOp&gt; optable;


	float execute(float input1, float input2) {

		auto itor = optable.find(foo);
		if (itor != optable.end()) {
			auto&amp; fn = itor-&gt;second;
			(this-&gt;*fn)(input1, input2);
		}
		return 0;
	};
};

Or map to lambda functions:

float execute(float input_1, float input_2) {


	static std::unordered_map&lt;int, std::function&lt;float(float, float)&gt;&gt; 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-&gt;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.

huangapple
  • 本文由 发表于 2023年7月6日 15:25:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76626418.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定