C++使用策略模式,减少使用switch...case...

2023-12-13 20:14:55

原理

在这里插入图片描述

函数

#include <iostream>
#include <functional>
#include <map>

void fun1(int a, int b)
{
	std::cout << "fun1 : a ="<<a<<"	b ="<<b;
}


void fun2(int a, int b)
{
	std::cout << "fun2 : a =" << a << "	b =" << b;
}

int main()
{

	// 可以改变这个值来调用不同的函数
	int id = 1;

#if 0
	switch (id)
	{
	case 1:
		fun1(0, 0);
		break;
	case 2:
		fun1(0, 0);
		break;
	}
#endif
	
	std::map<int, std::function<void(int,int)>> functionMap;

	functionMap[1] = [](int a, int b) { fun1(a,b); };
	functionMap[2] = [](int a, int b) { fun2(a, b); };

	
	if (functionMap.find(id) != functionMap.end()) {
		// 调用对应的函数并传递参数
		functionMap[id](0,0);
	}
	else {
		std::cout << "Invalid id" << std::endl;
	}

	return 0;
}

类+模板函数

因为工作职位低,无权对父类进行修改;
业务上又大量使用switch…case…操作模板函数;搞得代码量暴涨!

使用switch…case…

#include <iostream>
#include <functional>
#include <map>
#include <string>
#include <tuple>
#include <type_traits>

// 因为没有Equip的修改权限
struct Equip {
	std::string code;       //装备
};

struct FATable:public Equip {
	int idFA;               //方案ID
	std::string nameId;     //名称ID
	std::string equipId;    //装备ID
	int equipNum;           //装备数量
public:
	void write(int info) {
		std::cout << "FATable = " << info;
	};
};

struct NTable {
	std::string name;       //装备名称
	std::string nameId;     //装备ID
	int classify;           //分类ID
public:
	void write(int info) {
		std::cout << "NTable = " << info;
	};
};

struct CTable {
	int classify;           //分类ID
	std::string className;  //分类名称
public:
	void write(int info) {
		std::cout << "CTable  = "<< info;
	};
};

template<typename T>
inline void writeIn(int info) {
	T().write(info);
};

int main()
{

	// 可以改变这个值来调用不同的函数
	const int id = 1;

#if 1
	switch (id)
	{
	case 0:
		writeIn<FATable>(0);
		break;
	case 1:
		writeIn<NTable>(0);
		break;
	case 2:
		writeIn<CTable>(0);
		break;
	}
#endif
	
	return 0;
}

不使用switch…case…

#include <iostream>
#include <functional>
#include <map>
#include <string>
#include <tuple>
#include <type_traits>

// 因为没有Equip的修改权限
struct Equip {
	std::string code;       //装备
};

struct FATable:public Equip {
	int idFA;               //方案ID
	std::string nameId;     //名称ID
	std::string equipId;    //装备ID
	int equipNum;           //装备数量
public:
	void write(int info) {
		std::cout << "FATable = " << info;
	};
};

struct NTable {
	std::string name;       //装备名称
	std::string nameId;     //装备ID
	int classify;           //分类ID
public:
	void write(int info) {
		std::cout << "NTable = " << info;
	};
};

struct CTable {
	int classify;           //分类ID
	std::string className;  //分类名称
public:
	void write(int info) {
		std::cout << "CTable  = "<< info;
	};
};

template<typename T>
inline void writeIn(int info) {
	T().write(info);
};

int main()
{

	// 可以改变这个值来调用不同的函数
	const int id = 1;

	std::tuple<FATable, NTable, CTable> g_type = { FATable(), NTable(), CTable()};

	// 使用 decltype 来获取 g_type 中的元素类型,并将其命名为 _mT。
	using  _mT = decltype(std::get<id>(g_type));

	// 使用 std::remove_reference 来移除 _mT 类型的引用修饰符,将结果命名为 CleanType。
	using CleanType = typename std::remove_reference<_mT>::type;

	// 将 CleanType 作为模板参数传递
	writeIn<CleanType>(0);
	return 0;
}

知识点

decltype

decltype 是 C++11 引入的一个关键字,用于获取表达式的类型。它可以用于编译时推导表达式的类型,而不需要显式地指定类型。

  • 以下是 decltype 的一些重要知识点:

decltype 的语法:decltype(expression)

  • expression 是一个表达式,可以是变量、函数调用、成员访问等。

  • decltype 的返回类型:

如果 expression 是一个标识符或类成员访问表达式,decltype 返回该标识符或成员的类型。

如果 expression是一个函数调用表达式,decltype 返回函数的返回类型。

如果 expression是一个右值表达式,decltype返回右值的类型。

如果 expression 是一个左值表达式,decltype 返回左值的引用类型。

  • decltype 的应用场景:

在模板编程中,可以使用 decltype 推导模板参数的类型,以便在编译时确定类型。

可以使用 decltype 推导 lambda表达式的返回类型。

可以使用 decltype 推导复杂表达式的类型,避免手动指定类型。

-以下是一些使用 decltype 的示例:

	int x = 42;
	decltype(x) y;					// y 的类型为 int

	std::vector<int> vec = { 1, 2, 3 };
	decltype(vec.size()) size;		// size 的类型为 std::vector<int>::size_type

	auto lambda = [](int a, int b) -> int { 
		std::cout << "a + b  = " << a + b;
		return a + b; 
	};
	decltype(lambda) func = lambda;	// func 的类型为 lambda 表达式的类型
	func(1,1);

	template <typename T, typename U>
	auto add(T t, U u) -> decltype(t + u) {
		return t + u;
	}
	auto result = add(3, 4.5);		// result 的类型为 double

#include <iostream>
#include <typeinfo>
int main() {
     auto f = []()->void {
        std::cout << "hello---19" << std::endl;
     };
     using FunctionType = decltype(f);              // 使用 decltype(f) 定义类型别名 FunctionType
     std::cout << typeid(f).name() << std::endl;    // 输出类型名称
     std::cout << typeid(FunctionType).name() << std::endl;  // 输出类型别名的名称
     FunctionType func = f;                          // 使用类型别名创建变量,并将 f 赋值给它
     func();  // 调用函数对象
     /*
         使用 decltype 推导出的函数类型,不能直接声明一个未初始化的变量并调用它
         错误用法:
         FunctionType func;
         func();
     */
     return 0;
}

在这里插入图片描述
在这里插入图片描述

std::remove_reference

std::remove_reference 是 C++ 标准库中的一个模板元函数,用于移除类型的引用修饰符
当您使用std::remove_reference 时,它将返回一个新类型,该类型是从给定类型中移除了引用修饰符的版本。

  • 以下是 std::remove_reference 的示例用法:
#include <iostream>
#include <type_traits>

int main() {
    // 定义一个带有引用修饰符的类型
    using TypeWithReference = int&;

    // 使用 std::remove_reference 移除引用修饰符
    using TypeWithoutReference = 
    std::remove_reference<TypeWithReference>::type;

    // 输出移除引用修饰符后的类型名称
    std::cout << "Type without reference: " 
    << typeid(TypeWithoutReference).name() << std::endl;

    return 0;
}

在这个示例中,TypeWithReference 是一个带有引用修饰符的类型,然后我们使用 std::remove_reference 来移除引用修饰符,得到了 TypeWithoutReference。最后,我们输出了移除引用修饰符后的类型名称。

请注意,在 C ++14及更高版本中,你可以使用简化形式 std :: remove _ reference _ t 代替
typename std :: remove _ reference < T >:: type以缩短代码:

using CleanType = std::remove_reference_t<TypeWithReference>;

这提供了相同的结果,即从类型中去除引用

文章来源:https://blog.csdn.net/qq_47355554/article/details/134819804
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。