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

原理

在这里插入图片描述

函数

#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>;

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

相关推荐

  1. 16 | 缓存策略:如何使用缓存来减少磁盘IO?

    2023-12-10 15:06:02       34 阅读
  2. 设计模式-策略模式-使用

    2023-12-10 15:06:02       32 阅读
  3. 策略模式结合Spring使用

    2023-12-10 15:06:02       26 阅读
  4. Springboot日常开发使用策略、工厂模式

    2023-12-10 15:06:02       66 阅读
  5. 策略模式--在SpringBoot中的使用

    2023-12-10 15:06:02       48 阅读
  6. 策略模式在springboot中的使用

    2023-12-10 15:06:02       32 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-10 15:06:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-10 15:06:02       106 阅读
  3. 在Django里面运行非项目文件

    2023-12-10 15:06:02       87 阅读
  4. Python语言-面向对象

    2023-12-10 15:06:02       96 阅读

热门阅读

  1. ClickHouse为何如此之快

    2023-12-10 15:06:02       61 阅读
  2. qt:使用信号槽机制传参

    2023-12-10 15:06:02       63 阅读
  3. 数据结构之内部排序

    2023-12-10 15:06:02       44 阅读
  4. pandas常见问题汇总

    2023-12-10 15:06:02       63 阅读
  5. 使用python实现断点续传

    2023-12-10 15:06:02       48 阅读
  6. 特权FPGA学习笔记

    2023-12-10 15:06:02       55 阅读
  7. s3-dist-cp 介绍教程示例使用方法

    2023-12-10 15:06:02       49 阅读
  8. 机器人IC

    2023-12-10 15:06:02       48 阅读