switch-case 문에서 case가 많을 때, 간단하게 줄이는 방법
switch-case 문을 쓰다 보면, case가 선형적으로 계속 늘어나는 경우가 발생한다. 패킷을 처리할 때, 주로 발생한다. 패킷의 종류가 늘어나면, 늘어나는 만큼 case가 증가한다. case가 늘어날 때마다 선형적으로 계속 코드가 증가하는 것을 해결할 수 있을까
우선 생각나는 방법은 case에 대응하는 함수를 만들어서 처리하는 것이다. case가 증가할 때, case를 처리하는 함수들을 만들면 switch-case 문의 코드는 줄어든다. case 0: break; 같은 문장은 여전히 존재한다. 함수로 만들었으므로, 함수 호출에 대한 비용이 추가로 발생한다. 코드의 양은 생각보다 줄지 않았지만, 추가 비용이 발생한 것이다.
비용을 감내하고 더 코드를 줄일 수 있는 방식이 있다. 함수들의 시그내쳐(인자 및 반환값)를 통일시키고 함수 포인터를 타입으로 갖는 배열을 만드는 것이다. 배열의 인덱스가 case에 해당하고, 인덱스에 해당하는 함수를 호출하면 case를 처리하는 것이다.
아래는 처리 방식의 예시이다.
#include <iostream>
using FuncPtr = void(*)(int);
void Case_0(int val);
void Case_1(int val);
void Case_2(int val);
void Case_3(int val);
void Case_4(int val);
int main()
{
/*
문제 상황 switch-case분류가 너무 많아!
*/
// 태초에 뭔가 코드가 있었음.
// 코드 실행 결과가 data와 case를 가리키는 정수 target
// 근데 귀찮으니 편의상 data와 target을 지정하자
int data = 100;
int target = 10;
switch (target)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
//...
// 이게 너무너무많아!!!!!!!!!!!!!
//...
case 100:
break;
default:
break;
}
// 위 상황을, 함수포인터를 타입으로 갖는 배열을 이용해서 해결할 수 있음
// using FuncPtr = void(*)(int); 로 타입을 지정하고
// 초기화하는 코드들에 일케 넣어주고
FuncPtr funcArr[5];
funcArr[0] = Case_0;
funcArr[1] = Case_1;
funcArr[2] = Case_2;
funcArr[3] = Case_3;
funcArr[4] = Case_4;
// switch-case문을 아래로 대체하면됨.
data = 10;
target = 2;
//target이 배열의 인덱스 허용 범위에서만 되도록 거르긴해야함.
funcArr[target](data);
return 0;
}
void Case_0(int val)
{
std::cout << "Hi~ im case 0 :" << val << std::endl;
}
void Case_1(int val)
{
std::cout <<"Hi~ im case 1 :" << val << std::endl;
}
void Case_2(int val)
{
std::cout << "Hi~ im case 2 :" << val << std::endl;
}
void Case_3(int val)
{
std::cout << "Hi~ im case 3 :" << val << std::endl;
}
void Case_4(int val)
{
std::cout << "Hi~ im case 4 :" << val << std::endl;
}
여전히 함수를 호출하는데 들어가는 비용(함수 호출 비용, 함수를 만들어서 관리해야 하는 비용 등)이 추가된다. 대신, switch-case문에 들어가는 코드를 많이 줄일 수 있다.
이 외에도, 만약 객체에서 처리한다면, 다형성을 이용해서 처리할 수도 있을 것 같다. 대신, 구체 클래스가 case만큼 늘어나게 될 것 같다. 클래스를 관리하는 관습은 클래스 하나에 파일 하나이다. 그런데, case만큼 클래스를 늘리고 이 클래스를 모두 파일로 관리하면 파일이 너무 많아진다. 따라서, 소수의 파일에 클래스를 몰아두게 되지 않을까 싶다.