C++11模板优化

c++11对模板添加了很多内容,如对函数模板默认参数的支持,模板别名

一、模板别名

具体用法:using 别名 = 需要替代的模板,使用模板别名替代长模板能极大地提高代码的简洁性和清晰度,但是如果滥用模板别名会导致代码的可读性降低,所以建议只在长模板时使用,例如简单的vector<int>不应该使用别名,使用别名反而让人无法第一时间了解意图且完全没必要

使用示例:

#include <iostream>
#include <string>
#include <map>

template<typename T>
using StringMap = std::map<std::string, T, std::less<>>;

int main()
{
	StringMap<int> myMap;
	myMap["apple"] = 5;
	myMap["cherry"] = 8;
	myMap["banana"] = 4;

	for (auto& pair : myMap) {
		std::cout << pair.first << " :" << pair.second << std::endl;
	}
	std::cout << "\n";
	StringMap<std::string> anotherMap;
	anotherMap["dog"] = "woof";
	anotherMap["cat"] = "meow";
	anotherMap["bird"] = "tweet";

	for (const auto& pair : anotherMap) {
		std::cout << pair.first << ": " << pair.second << std::endl;
	}

	return 0;
}

二、函数模板默认参数

在C++11以前只能使用类模板默认参数,但是在C++11中添加了对函数模板默认参数的支持,函数模板的参数推导允许您在调用函数时省略显式的模板参数列表。这在编写泛型代码时特别有用,因为它减少了需要手动指定的类型信息。然而,需要注意的是,当模板参数不能完全从函数参数推导出来时,您仍然需要显式指定这些参数。例如,当函数模板有多个模板参数,但只有部分参数可以从实参推导时,剩下的参数需要显式指定。

template <typename T = int>
class MyClass {
    // ...
};//正确

// 在C++98或C++03中,这是不允许的
template <typename T = int>
void myFunction() {
    // ...
}

函数模板的使用

#include <iostream>
#include <string>
#include <map>

template <typename T>
class base {
public:
	void print(T a) {
		std::cout << a << std::endl;
	}
};

template <typename T = int>
class child {
public:
	void print(T a) {
		std::cout << a << std::endl;
	}
};

template <typename T>
void function1(T a)
{
	std::cout << a << std::endl;
}

template <typename T = int>
void function2(T a)
{
	std::cout << a << std::endl;
}

template <typename R,typename T>
R function3(T a)//因为无法通过T直接推导出R,所以无法实现像普通函数一样调用,只能显示显示调用
{
	return a;
}

template <typename R = int,typename T>//默认参数写在参数列表最后,这是与普通函数的区别之一
R function4(T a)
{
	return a;
}


int main()
{
	function1("nihao");//自动推导
	function2("aha");//自动推导
	
	base<std::string> mybase;
	mybase.print("nihao"); //输出nihao

	child<> mychild;//使用默认参数int
	mychild.print(10); //输出10
	
	auto result1 = function3<double>(10); // 明确指定返回类型为 double
	auto result2 = function4(10);         // 返回值使用默认参数 int,T 被推导为 int

	return 0;
}

我们能够观察到,模板函数有些情况下是能够像普通函数一样被调用的(只要函数模板的所有模板参数都能被推导出来,那么该模板函数就能像普通函数一样调用,否则就需要给无法推导的参数显式的指定类型),但模板类即使每一个参数都有默认参数也必须写成带<>的形式,即模板实例,因为类模板本身只是一个模板,它定义了如何生成具体类型的蓝图,当您实例化一个模板类时,编译器根据模板参数生成具体的类类型。使用尖括号也是告诉编译器您正在创建一个模板类的实例,而不是使用一个普通类或者访问一个静态成员。

三、需要注意的点

1. 默认参数的区别:与普通函数的默认参数不同,第一,函数模板的默认参数是对类型的默认设定,而不是对函数参数值的默认设定,第二,函数模板的默认参数可以出现在模板参数列表中的任何位置,而不像普通函数的默认参数只能放在参数列表的末尾。
2. 模板参数的自动推导:当调用一个函数模板时,C++ 编译器会尝试根据提供的实参自动推导模板参数的类型。如果无法推导出类型,编译器会回退到使用默认模板参数(如果有的话)。如果既无法推导出类型,也没有默认模板参数,编译器则会报错。
3. 模板实例化:对于类模板,即使所有模板参数都提供了默认值,你仍然需要使用尖括号 <> 来实例化模板(即使尖括号内没有内容)。这是因为编译器需要明确知道这是一个模板实例化的操作。
4.模板代码的性能考虑:虽然模板提供了极大的灵活性和强大的泛型能力,但滥用模板可能导致编译时间显著增长,特别是在大型项目中。过度复杂的模板元编程也可能使得最终的二进制文件体积变大。合理使用模板,并在必要时倾向于简单、清晰的设计

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值