c++之旅:函数模板
函数模板
函数模板主要是泛型在函数的中的应用,通过泛型可以让函数处理各种各样的数据类型
简单的列子
#include <iostream>
using namespace std;
template <typename T> //定义泛型T
T add (T t1, T t2) {
return t1 + t2;
}
int main () {
cout << add(10.5, 0.8) << endl;
}
上面的例子中首先定义了泛型T,然后在add函数中使用了泛型,typename关键字也可以写成class。
明确指定类型
#include <iostream>
#include <string>
using namespace std;
template <typename T, typename E> //定义泛型T
E add (T t, E e) {
if (t > 1)
return e + "1";
else
return e + "1.5";
}
int main () {
cout << add<int, string>(10, "hello") << endl;
}
上面的代码中我们在调用add时显示的指定传入的类型
函数模板的重载
函数的模板的重载可函数的重载一个道理,都是通过函数名和函数参数列表来确定的
#include <iostream>
#include <string>
using namespace std;
template <typename T>
T test(T t) {
return t;
}
template <typename T>
T test(T t, int n) {
return n;
}
int main () {
cout << test<int>(3) << endl;
cout << test<float>(3.5, 10) << endl;
}
第一个test
函数包装器
模板函数中不仅能接受普通类型作为参数,还能接受函数。当使用函数作为参数时,需要用到函数包装器
#include <iostream>
#include <functional>
using std::cout;
using std::endl;
using std::function;
template <typename V, typename F>
V add (V v1, V v2, F f) {
return f(v1, v2);
}
int main () {
function<int(int, int)> fun = [](int v1, int v2) {
return v1 + v2;
};
cout << add(1, 2, fun) << endl;
}
上面的代码中需引入functional库,并定义了一个函数。
function<int(int, int)> fun = [](int v1, int v2) {
return v1 + v2;
};
中括号中第一个int表示返回值类型,后面的小括号表示函数接受的参数。函数包装器的实质时函数指针。通过函数包装器我们可以在一个函数内部定义一个函数了。
函数包装器指向外部函数
#include <iostream>
#include <functional>
using namespace std;
void test(int i, int j) {
cout << i << j << endl;
}
int main () {
function<void(int, int)> fun = test;
fun(1,3);
}
引用包装器
要想在函数模板内部修改传入的值,需要传递变量的引用或者指针,一般情况下,我们会将变量的引用传递进去,这时将函数模板参数设置为引用或者使用引用包装器。
函数接受引用
#include <iostream>
#include <string>
using namespace std;
template <typename T>
void test(T t) {
t = 100;
}
int main () {
int a = 10;
test<int&>(a);
cout << a << endl;
}
使用引用包装器
引用包装器有些问题,尽量避免使用
#include <iostream>
#include <functional>
using namespace std;
template <typename T>
void test(T t) {
t += 100;
}
int main () {
int a = 10;
test(ref(a));
cout << a << endl;
}
上面的代码中去掉模板中的+号就会便宜错误