当前访客身份:游客 [ 登录 | 加入 OSCHINA ]

代码分享

当前位置:
代码分享 » C/C++  » 编程基础
defddr

c++模板 template

defddr 发布于 2016年08月07日 14时, 0评/1272阅
分享到: 
收藏 +0
0
c++模板学习笔记
标签: <无>

代码片段(1) [全屏查看所有代码]

1. [代码][C/C++]代码     跳至 [1] [全屏预览]

/**************************************
技术博客 http://www.cnblogs.com/itdef/ 
技术交流群 群号码:324164944 
欢迎c c++ windows驱动爱好者 服务器程序员沟通交
**************************************/
使用vc2015
进行C++ 模板的学习实验和笔记 用简单示例学习了解STL


template大部头理论书  讲解各种规则和各种规则例外的解决办法 集中精力在20%的规则中的阴暗角落而不是80%实践中要注意的东西

https://github.com/wuye9036/CppTemplateTutorial
这个模板教程是强烈推荐 易懂 看完可用于个人的一些代码中进行模板编程 实用


第一个示例
//=============================================
int add(int a ,int b)
{
	return a+b;
}

int main()
{
	add(3,8);
	add(7,12);
	return 0;
}
//============================================
如果说
函数是变量之间的操作方式复用方案
比如 3+8 7+12 都是调用add函数
那么模板就是变量的类型的复用方案
比如

#include <iostream>
template<typename T>
const T& compare(T& a, T& b)
{
	return a > b? a :b;
}

int main()
{
	int a = 7, b = 8, c = 9, d = 3;
	std::cout << compare<int>(a, b) << std::endl;
	std::cout << compare(c, d) << std::endl;
	char f = 'f', g = 'z';
	std::cout << compare(f, g) << std::endl;
	return 0;
}

compare这个模板函数对于变量的比较方式都是一致的 ,就是比较两个变量的大小
而且对于 int 和 char 两种变量类型的比较都适用
就是我所说的对于变量的类型的复用方案
由于模板T对应的变量类型在本例中可以从函数参数推导得出 所以<int>这个符号并不强制需要写出来。

下面示例是一个链表 链表中每个节点可以存储不同类型元素
#include <iostream>
#include <string>

template<typename TYPE,typename NEXT>
struct AnyList {
	TYPE value;
	NEXT* next;
	AnyList(TYPE const &v,NEXT *n):value(v),next(n){}
};

int main()
{
	typedef AnyList<int, void> node_0;
	node_0 zero(4,NULL) ;
	typedef AnyList<char, node_0> node_1;
	node_1 one('z',&zero);
	typedef AnyList<std::string, node_1> node_2;
	node_2 two("test", &one);

	std::cout << two.value << std::endl;
	std::cout << one.value << std::endl;
	std::cout << zero.value << std::endl;

	std::cout << two.value << std::endl;
	std::cout << two.next->value << std::endl;
	std::cout << two.next->next->value << std::endl;
	
	return 0;
}

示意图:略

STL中FOREACH示例学习(函数指针模板参数)
#include <iostream>
#include <string>

template<typename T,void(*f)(T &v)>
void foreach(T array[], unsigned size)
{
	for (unsigned i = 0; i < size; ++i)
		f(array[i]);
}

template<typename T>
void inc(T& v) { ++v; }

template<typename T>
void dec(T& v) { --v; }

template<typename T>
void print(T& v) { std::cout << ' ' << v << std::endl; }

int main()
{
	int array[] = { 1,2,3,4,5,6,7,8 };

	foreach<int, print<int>>(array, 8);
	std::cout << std::endl;

	foreach<int, inc<int>>(array, 8);
	foreach<int, print<int>>(array, 8);
	std::cout << std::endl;

	foreach<int, dec<int>>(array, 8);
	foreach<int, print<int>>(array, 8);
	std::cout << std::endl;
	
	return 0;
}
FOREACH函数从模板接收操作类型和操作函数,从参数中接收要操作的数组和数组长度
//===============================================
指针与引用模板参数

#include <iostream>
#include <string>

template<typename T>
class wrapper;

template<typename T>
class wrapper<T*> {
public:
	T* p;
	wrapper(T* t):p(t){}
	T get() { return *p; }
	void set(T v) { *p = v; }
};


template<typename T>
class wrapper<T&> {
public:
	T& p;
	wrapper(T& t) :p(t) {}
	T get() { return p; }
	void set(T v) { p = v; }
};


int global_variable_int = 0;

char global_variable_char = 'Z';

std::string global_variable_str = "this is a test";

int main()
{
	
	wrapper<int*> gwrapper1(&global_variable_int);
	gwrapper1.set(1);
	std::cout << gwrapper1.get() << std::endl;

	wrapper<int&> gwrapper2(global_variable_int);
	gwrapper2.set(2);
	std::cout << gwrapper2.get() << std::endl;

	wrapper<char*> gwrapper3(&global_variable_char);
	gwrapper3.set('a');
	std::cout << gwrapper3.get() << std::endl;

	wrapper<char&> gwrapper4(global_variable_char);
	gwrapper4.set('g');
	std::cout << gwrapper4.get() << std::endl;

	wrapper<std::string*> gwrapper5(&global_variable_str);
	std::cout << gwrapper5.get() << std::endl;

	wrapper<std::string&> gwrapper6(global_variable_str);
	gwrapper6.set("finish test");
	std::cout << gwrapper6.get() << std::endl;
	
	return 0;
}

根据参数的不同 自动选择不同的模板函数 指针或者引用
//======================================
模板的模板参数
如果模板中的模板不参与推导 可以省略不写
#include <iostream>
#include <string>

//template<template<typename TT> class Func, typename T>
template<template<typename> class Func, typename T>
void foreach(T array[], unsigned size)
{

	Func<T> func;
	for (unsigned i = 0; i < size; ++i)
		func(array[i]);
}

template<typename T>
struct inc {
	void operator()(T& v) { ++v; }
};

int main()
{
	int arr[] = { 1,2,3,4,5 };
	foreach<inc>(arr,5);
	return 0;
}

//====================================================
特化匹配示例
// 11111.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <string>

template<typename T0,typename T1,typename T2>
struct S {
	std::string id() { return "General"; }
};

template<typename T0,typename T1>
struct S<T0, T1, char>
{
	std::string id(){ return "#1"; }
};

template<typename T0>
struct S<T0, char, char>
{
	std::string id() { return "#2"; }
};

template<typename T>
struct S<int, T, T>
{
	std::string id() { return "#3"; }
};


int main()
{
	std::cout << S<float, float, float>().id() << std::endl;
	std::cout << S<int, int, int>().id() << std::endl;
	std::cout << S<int, int, char>().id() << std::endl;
	std::cout << S<char, char, char>().id() << std::endl;
	// 歧义
	//std::cout << S<int, char, char>().id() << std::endl;

    return 0;
}

//========================================================
模板的递归示例

// 11111.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <string>

template<int i>
int mult()
{
	return i * mult<i - 1>();
}

template<>
int mult<1>()
{
	return 1;
}

int main()
{
	std::cout << "mult<4> = " << mult<4>();
    return 0;
}



开源中国-程序员在线工具:Git代码托管 API文档大全(120+) JS在线编辑演示 二维码 更多»

开源从代码分享开始 分享代码
defddr的其它代码 全部(29)...