C++模板 - policy类

一讲到traits,相应的就会联系到policy。那么policy是干啥的呢?

看一下下面的累加代码。

template<class T, class P>
typename traits<T>::AccuT accum(const T* ptr, int len)
{
	traits<T>::AccuT total = traits<T>::Zero();

	for (int i = 0; i < len; i++)
	{
		total += *(ptr + i);
	}

	return total;
}

注意total += *(ptr + i);这一行。这里有两个问题:

1. 并不是所有的类型都支持+=操作符的,如果传进来的是一个自定义类型,而且没有定义+=,怎么办?

2. 如果并不想使用+=,比如传进来的是个字符串,然后想逆序拼接。

想解决这2个问题,首先想到的应该就是这个地方不要hard code了,通过传进来参数的方法来动态修改这行代码。

一般有两种办法:

1. 传进来一个函数对象,然后通过函数对象来调用相应的函数

2. 使用policy类。

这里介绍第二种方法:policy

我们把累加函数改成:

template<class T, class P>
typename traits<T>::AccuT accum(const T* ptr, int len)
{
	traits<T>::AccuT total = traits<T>::Zero();

	for (int i = 0; i < len; i++)
	{
		P::accumulate(total, *(ptr + i));
	}

	return total;
}

注意我们多加了一个模板参数P, 然后调用P::accumulate(total, *(ptr + i));

现在我们来定义这个P类:

class P
{
public:
	template<class T1, class T2>
	static void accumulate(T1& total, T2 v)
	{
		total += v;
	}
};

P类里面只有一个函数,是个静态模板函数。

这样,我们就可以调用了:

	int sz[] = {1, 2, 3};
	traits<int>::AccuT avg = accum<int, P>(sz, 3) / 3;

得到结果2.

那如果我现在要传入一个字符数组,并且想逆序拼接,应该怎么做呢?

首先把char traits返回类型改成string:

template<>
struct traits<char>
{
	typedef std::string AccuT;
	static AccuT Zero(){ return std::string(); };
};

然后新增一个policy类:

class P2
{
public:
	template<class T1, class T2>
	static void accumulate(T1& total, T2 v)
	{
		total.insert(0, 1, v);
	}
};

调用一下就会发现返回值是cba了。

char str[] = {'a', 'b', 'c'};
auto ret = accum<char, P2>(str, 3);

如果调用auto ret = accum<char,
P>(str,
3);就会返回abc,因为string本身也支持+=,所有P::accumulate可以正常运行,并且是顺序拼接。

这就是policy的使用,通过policy我们可以替换累加函数里面的累加算法,很灵活。

完整代码:

// ConsoleApplication1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <memory>

#include <algorithm>
#include <numeric>
#include <string>

template<typename T>
struct traits;

template<>
struct traits<char>
{
	typedef std::string AccuT;
	static AccuT Zero(){ return std::string(); };
};

template<>
struct traits<int>
{
	typedef double AccuT;
	static AccuT Zero(){ return 0.0; };
};

template<class T, class P>
typename traits<T>::AccuT accum(const T* ptr, int len)
{
	traits<T>::AccuT total = traits<T>::Zero();

	for (int i = 0; i < len; i++)
	{
		P::accumulate(total, *(ptr + i));
	}

	return total;
}

class P
{
public:
	template<class T1, class T2>
	static void accumulate(T1& total, T2 v)
	{
		total += v;
	}
};

class P2
{
public:
	template<class T1, class T2>
	static void accumulate(T1& total, T2 v)
	{
		total.insert(0, 1, v);
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	int sz[] = {1, 2, 3};
	traits<int>::AccuT avg = accum<int, P>(sz, 3) / 3;

	char str[] = {'a', 'b', 'c'};
	auto ret = accum<char, P>(str, 3);

	ret = accum<char, P2>(str, 3);

	return 0;
}
时间: 2024-10-23 20:08:01

C++模板 - policy类的相关文章

C++ template —— trait与policy类(七)

第15章 trait与policy类------------------------------------------------------------------------------------------------------------模板让我们可以针对多种类型对类和函数进行参数,但我们并不希望为了能够最大程度地参数化而引入太多的模板参数,同时在客户端指定所有的相应实参往往也是烦人的.我们知道我们希望引入的大多数额外参数都具有合理的缺省值.在某些情况下额外参数还可以有几个主参数来

函数模板与类模板

函数模板,顾名思义,是在生成函数时依照的模板. 有时,我们需要对不同的数据类型做同样的函数操作. 比如:分别对一个int类型数 和 一个double类型数求平方. 这时,虽然都是同样的求平方操作(函数体内代码一样),但是我们必须要编写两个不同的函数,因为处理int类型的函数的参数和返回值类型都应该是int,而处理double类型的函数的参数和返回值都应该是double. 如下:函数体内操作代码一样,设计为重载函数,用相同的函数名,但是参数类型和返回值类型却都不一样,函数需要定义两次. int S

20Spring_JdbcTemplatem模板工具类

JdbcTemplate 是Spring提供简化Jdbc开发模板工具类.为了更好的了解整个JdbcTemplate配置数据库连接池的过程,这篇文章不采用配置文件的方式,而是采用最基本的代码 的方式来写.后一篇文章会讲配置文件的方式. 1.Spring 对一下的持久层技术支持 2.jdbcTemplate快速入门 第一步:在项目中导入jar包 其中Spring核心包有四个,日志包有两个,测试包一个.如下 因为要用到jdbcTemplate所以还要导入以下两个jar包 spring-jdbc-3.2

实验11:Problem D: 分数类的模板数组类

在默认构造函数里面,分母的默认值不能为0!! Home Web Board ProblemSet Standing Status Statistics Problem D: 分数类的模板数组类 Problem D: 分数类的模板数组类 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 509  Solved: 350[Submit][Status][Web Board] Description 封装一个模板数组类Array,支持一下操作: 1. 构造函

C++学习之模板 ----函数模板、类模板

本博文主要讨论函数模板与类模板以及其简单应用. 1).作用:函数模板和类模板都可以看做是一种代码产生器,往里面放入具体的类型,得到具体化的函数或者class. 2).编译(分为两步): a):实例化之前,先检查模板本身语法是否正确: b):根据 函数调用或者类模板调用 ,先去实例化模板代码,产生具体的函数/类. 也就是说, 没有函数调用或者类类型对象声明,就不会实例化模板代码,在目标文件obj中找不到模板的痕迹. 3):优缺点 模板的缺点是代码膨胀,编译速度慢,而优点是运行速度快. 一.函数模板

PHP模板解析类实例

作者:mckee 这篇文章主要介绍了PHP模板解析类,涉及php针对模板文件的解析与字符串处理的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下 1 <?php 2 class template { 3 private $vars = array(); 4 private $conf = ''; 5 private $tpl_name = 'index'; 6 //如果模板不存在 会查找当前 controller默认index模板 7 private $tpl_suffix = '.html

C++笔记(7):泛型编程和模板(函数模板和类模板)

泛型编程和模板 0.泛型编程 1.函数模板 2.类模板 ----------------------------------------------------------------------------------------------------------- 0.泛型编程 所谓泛型就是以独立于任何特定类型的方式编写代码.前面介绍的标准库的容器.迭代器和算法都是泛型编程的具体应用. 模板是泛型编程的基础.使用模板的时候不需要知道模板是如何定义的,但今天我们来介绍如何定义自己的模板类和模

PHP 自定义 Smarty 模板引擎类 高洛峰 细说PHP

smarty模板引擎类简单工作原理 利用Smarty 模板引擎类对模板文件中的变量进行编译,编译过程其实就是利用正则表达式翻译成PHP文件.例如 模板文件中{$title} 利用正则表达式找到并替换成  <?php echo $this->vars['title'];?> 自定义 Smarty 模板引擎类 smarty.class.php页面 <?php /*  * 自定义Smarty模板引擎类  */         class Smarty{             priva

【C/C++学院】0825-类模板/final_override/类模板与普通类的派生类模板虚函数抽象模板类/类模板友元/位运算算法以及类声明/Rtti 实时类型检测/高级new创建/类以及函数包装器

类模板 类模板多个类型默认类型简单数组模板 #pragma once template <class T=int>//类模板可以有一个默认的值 class myArray { public: myArray(); ~myArray(); }; #include "myArray.h" template <class T=int>//每一个函数都需要加上一个默认的值 myArray<T>::myArray() //类模板成员函数在外部,需要加载类型初始