在模板编程中,有几个常用的技术:模板(偏)特化,特性萃取,标签分派,匹配失败不是错误。其中模板(偏)特化是基础,匹配失败不是错误(SFINAE)应用最为广泛。

现代C++对模板编程做了更多的加强,boost.hana又结合constexpr和lambda把类型与值的计算统一了起来。放眼C++世界,尤其是C++库,几乎都是使用模板的泛型编程。

话说在C++的世界中(并且几乎所有语言中)函数的作用是最为明显的,试想:没有类也可以完成编程任务,但没有函数却不好说。另一方向只使用变量和语句也能完成少量的工作,但不进行函数的封装终难成大事。这几年函数式编程赿来赿流行,与函数的重要性不无关系。所以无论是用类也罢,用函数也罢,或者使用C++新增的变量模板,我们的思路是始终围绕着把它们向函数上靠就好。从MPL的元函数开始就试图使类尽可能像函数,我们在模板编程中也要使模板类、模板变量、乃至模板函数都向“函数”靠拢。这里函数加上引号我想表达的是包括但不限于constexpr函数。

一、先从类型计算将用类实现来转为用函数实现起。将类型计算与值计算统一起来,以例子说话:

 #include <type_traits>

 //1、先定义一个辅助类,为了将类型表示为对象
template<typename T>
struct type_t
{
using type = T;
}; //2、装饰类型,这里给类型添加指针
template<typename T>
constexpr auto add_pointer(type_t<T>)
{
return type_t<T*>{};
} //3、为测试提供支持
template<typename T>
constexpr auto is_pointer(type_t<T>)
{
return std::false_type{};
} template<typename T>
constexpr auto is_pointer(type_t<T*>)
{
return std::true_type{};
} //4、测试
type_t<int> int_t{};
auto p = add_pointer(int_t); auto is_ptr = is_pointer(p);
static_assert(is_ptr.value,""); int main()
{
return ;
}

我们没有用元函数式方法实现,因为STL库中实现好了。现在用函数的方式也可以实现了,仔细体会代码,函数把类型和值的计算统一了起来,看起来函数的作用更加强大了。针对以上例子,我们需要类型的时候可以这样

 // --vs2017rc仍然不能编译--
//template<typename T>
//using point_type =typename decltype(add_pointer(type_t<T>{}))::type; using point_type = typename decltype(p)::type;

稍嫌繁琐,但可以进一步封装。

 //将以上代码装到namespace中
namespace detail {
//...
} template<typename T>
uisng add_pointer_t = typename decltype(detail::add_pointer(type_t<T>{}))::type;

二、把类函数化。还是以例子说话:

 struct test {};

 //1、古老的仿函数
template<typename T>
struct func
{
template<typename... Args>
auto operator()(Args&&... args) const
{
return T{ std::forward<Args>(args)... };
}
}; func<test> func_c;
auto test_t=func_c(); //2、元函数,就不写例子了,STL中很多

func明明是类,但我们把它用出了函数的感觉有没有。

三、把变量模板函数化

上面的代码感觉用起来还是不爽,主要是因为还要先生成一个类对象,我们把它也封装起来,再看个例子

 struct test2
{
explicit test2(int x)
: x_(x)
{ } int x_;
};
template<typename T>
constexpr func<T> func_c{}; auto test2_t = func_c<test2>();

看起来就像在调用函数了吧。

总之,不管是什么,只管往函数上靠就对了。

本来想要写sfinae来着,却强烈地想函数的事,现在记录一种利用sfinae的方式吧。

首先,当然是模板特化了。特化前先说说形式完整性这个概念:

有一个别名声明:

 template<typename...>
using void_t=void;

这个别名声明的意思是不管你给我传多少个模板参数,可能是有效的参数我都统统把它们当做void,除非任意一个模板参数不是有效的,那样的话另说(通常是编译器会给你点颜色看看)。

今天我就是要给你无效参数了怎么地?哼哼,我有sfinae大法在手,给我脸色我还不尿你呢!

有了sfinae,编译器会妥协,不管模板参数有效无效它都不敢给你脸色啦。

嗯,我想想哈,举个标签的例子吧。设想是如果一个类有标签,那么我们获取它的标签,如果没有,就什么也不做。

     template<typename T, typename = void>
struct tag_of; template<typename T>
struct tag_of<T, void_t<typename T::tag>>
{
using type = typename T::tag;
}; template<typename T>
using tag_of_t = typename tag_of<T>::type; template<typename T, typename Tag>
struct is_tagof : std::false_type
{ }; template<typename T>
struct is_tagof<T, tag_of_t<T>> : std::true_type
{ };

模板(偏)特化会优先得到解析。上面is_tagof判断类型T是否有嵌入的tag,如果有,is_tagof就是true_type,如果没有的话,编译器在匹配void_t<typename T::tag>会失败,编译器不认为这是错误而是回头匹配主模板,is_tagof就是false_type

C++模板杂谈的更多相关文章

  1. 子树大小平衡树(Size Balanced Tree,SBT)操作模板及杂谈

    基础知识(包括但不限于:二叉查找树是啥,SBT又是啥反正又不能吃,平衡树怎么旋转,等等)在这里就不(lan)予(de)赘(duo)述(xie)了. 先贴代码(数组模拟): int seed; int ...

  2. thinkphp5杂谈--模板

    一种新型开源模板   http://www.h-ui.net/H-ui.admin.shtml 下载页面代码 除了curl以外还可以借助  仿站小工具V7.0,操作示意图

  3. thinkphp5杂谈--项目架构和模板搭建(view视角)

    nginx网站配置 项目架构 项目文件夹 视图模板 一种出幺蛾子的访问办法 访问相关特色模块并渲染视图

  4. java游戏开发杂谈 - 游戏物体

    现实生活中,有很多物体,每个物体的长相.行为都不同. 物体存在于不同的空间内,它只在这个空间内发生作用. 物体没用了,空间就把它剔除,不然既占地方,又需要花精力管理. 需要它的时候,就把它造出来,不需 ...

  5. ~Delphi const 杂谈~

    来自:http://www.cnblogs.com/tibetwolf/articles/1785744.html ------------------------------------------ ...

  6. Jade模板引擎让你飞

    写在前面:现在jade改名成pug了 一.安装 npm install jade 二.基本使用 1.简单使用 p hello jade! 渲染后: <p>hello jade!</p ...

  7. ABP入门系列(2)——通过模板创建MAP版本项目

    一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...

  8. CMS模板应用调研问卷

    截止目前,已经有数十家网站与我们合作,进行了MIP化改造,在搜索结果页也能看到"闪电标"的出现.除了改造方面的问题,MIP项目组被问到最多的就是:我用了wordpress,我用了织 ...

  9. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

随机推荐

  1. 起步X5 的铛铛的安装部署过程

    (2017年1月)主要资料: 1.铛铛的IM Server即时通信服务使用 actor   https://github.com/actorapp/actor-platform ,开发者网站是:htt ...

  2. 苹果App Store开发者帐户从申请,验证,到发布应用(3)

    应用上架的流程和操作步骤 下面主要介绍一下,上架应用相关流程和相关的操作步骤:   1.登录itunes,https://itunesconnect.apple.com/WebObjects/iTun ...

  3. iOS数据存储

    [reference]http://www.infoq.com/cn/articles/data-storage-in-ios 谈到数据储存,首先要明确区分两个概念,数据结构和储存方式.所谓数据结构就 ...

  4. C# .NET修改注册表

    c#修改注册表,需要引用Microsoft.Win32命名空间 using Microsoft.Win32; //声明 ///引用 RegistryKey reg; reg = Registry.Cl ...

  5. [Angular Tutorial]PhoneCat Tutorial App

    (注:曾经在<不敢止步>一书中看到学到一个观点,作者认为学习一门技术最好的方法就是翻译某部领域书籍.这里我决定做一次尝试,接下来花1个月左右时间,将Angular Tutorial Pho ...

  6. KMP算法之查找模式串在源串中出现的次数

    问题描述: 给定两个字符串T, P.查找字符串P在字符串T中出现的次数. 解决方法: 典型的KMP算法的题目,在此使用的KMP算法为算法导论上介绍的算法.下一篇文章将详细介绍KMP算法的计算过程. 题 ...

  7. Aaron Swartz – 互联网天才开挂的人生历程:每时每刻都问自己,现在这世界有什么最重要的事是我能参与去做的?

    Aaron说的一句话让我挺有感触的-- 相信你应该真的每时每刻都问自己,现在这世界有什么最重要的事是我能参与去做的? 如果你没在做那最重要的事,那又是为什么? 1986年11月8日,有个叫Aaron ...

  8. centos 安装mysql 5.5.12

    1.安装gcc-c++  gcc make cmake编译器 2.安装ncurses 3.添加用户组 groupadd mysql useradd -r -g mysql mysql 4.安装 tar ...

  9. C语言的位运算的优势

    位运算加速技巧1. 如果乘上一个2的倍数数值,可以改用左移运算(Left Shift) 加速 300% x = x * 2;x = x * 64;//改为:x = x << 1; // 2 ...

  10. js模块化开发——前端模块化

    在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可:如今CPU.浏览器性能得到了极大的提升,很多页面逻辑迁移到了客 户端(表单验证等),随着web2.0时代的到来,Ajax技术 ...