目录
- 原理
- 函数
- 类+模板函数
- 使用switch...case...
- 不使用switch...case...
- 知识点
- decltype
- std::remove_reference
原理
函数
#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>;
这提供了相同的结果,即从类型中去除引用