C++真是一门自由的语言,虽然糖没有C#那么多,但是你想要怎么写,想要实现什么,想要用某种编程范式或者语言特性,它都会提供。

开大数运算类的新坑的时候(又是坑),无意中需要解决一个需求:大数类需要分别实现接受整数和浮点数的构造函数,构造函数中初始化类内保存数据的容器,所有整数的构造方法相同,所有浮点数的构造方法也相同,现在的目标是,找到一个机制,能尽可能少的实现代码,争取做到所有整数实现一份构造函数,所有浮点数实现一份构造函数。

学过C++的你一定会想到模板,这里有了

template<typename T>
Number(T num)
: _num(ToVectorBool(num))
{}

这里我用了vector<bool>来储存一个大数的二进制位模式,ToVectorBool是将数字转换为vector<bool>

但是现在的模板还没有Concept,如何来限制ToVectorBool接受的模板参数只能是整数和浮点数呢?你可能想到用模板的特例化,各种浮点数的实现成为特例,而剩下的整数使用非特例的实现,然后用static_assert来限定非特例实现中不是整数类型的T。

然而不要忘了,特例化的函数是要每个特例写一份代码的,这样多不优雅啊。同样是利用函数重载决议,我们需要一个筛选器,判断类型参数T是整数还是浮点数还是什么都不是。

这样我们就回到了模板元编程的范围,我们需要写一个MultiState模板结构,它接受一个T,和用来接受这个类型T并返回结果的模板结构,用我在模板元编程代码中的约定,就是接受TStatement和TPreds...,依次判断TStatement是否符合TPreds...里每个谓词,返回判断的结果:在第几个谓词哪里得到了TrueType。

我们还需要typedef出State<N>,正好我以前写过Int<N>模板整数类型,就用它了

本着用户不乱用的原则,MultiState本身不能把参数N暴露给用户,于是套了一层MultiStateImpl,用MultiState去“调用”MultiStateImpl

为了可扩展性,这里使用了变长模板参数包,做了一个template<class T> class... TPreds,这样可以用模板参数包的一些技巧,做出接受任意个谓词的MultiState

template<int N>
using State = Int<N>; template<int N, class TStatement, template<class T> class TPred, template<class T> class... TPreds>
struct MultiStateImpl
{
using Result = typename If<
typename TPred<TStatement>::Result,
State<N>,
typename MultiStateImpl<
N + ,
TStatement,
TPreds...
>::Result
>::Result;
}; template<int N, class TStatement>
struct MultiStateImpl
{
using Result = FalseType;
}; template<class TStatement, template<class T> class... TPreds>
struct MultiState
{
using Result = typename MultiStateImpl<, TStatement, TPreds...>::Result;
};

可以看到,代码里首先检查TPred<TStatement>::Result,如果正确,直接返回State<N>,否则,返回下一层MultiState<N+1,TStatement, TPreds...>的结果,如果都不成立,到了MultiState<N, TStatement>的实现,就直接返回FalseType,表示哪个都不满足。

爽啊,用起来就是这样的

template<typename TNumber>
Number::Number(TNumber& number)
: _num(ToVectorBool(number, MultiState<TNumber, IsInteger, IsFloat>::Result()))
{
} template<typename TInteger>
static std::vector<bool> Number::ToVectorBool(TInteger& intNumber, State<>)
{
//Integer 实现略
} template<typename TFloat>
static std::vector<bool> Number::ToVectorBool(TFloat& floatNumber, State<>)
{
//Float 实现略
} template<typename TOther>
static std::vector<bool> Number::ToVectorBool(TOther& other, FalseType)
{
static_assert(, "Not a number.");
}

还可以改,把State也做成模板参数包,State<1>这样的写法还不优雅

感觉怪怪的,不过好有意思

C++模板元编程 - 挖新坑的时候探索到了模板元编程的新玩法的更多相关文章

  1. h5 录音 自动生成proto Js语句 UglifyJS-- 对你的js做了什么 【原码笔记】-- protobuf.js 与 Long.js 【微信开发】-- 发送模板消息 能编程与会编程 vue2入坑随记(二) -- 自定义动态组件 微信上传图片

    得益于前辈的分享,做了一个h5录音的demo.效果图如下: 点击开始录音会先弹出确认框: 首次确认允许后,再次录音不需要再确认,但如果用户点击禁止,则无法录音: 点击发送 将录音内容发送到对话框中.点 ...

  2. Linux编程中的坑——C++中exit和return的区别

    今天遇到一个坑,折腾了一天才把这个坑填上,情况是这样的: 写了段代码,在main()函数中创建一个分离线程,结果这个线程什么都没干就直接挂掉了,代码长这样: int main() { 创建一个分离线程 ...

  3. 【模板篇】splay(填坑)+模板题(普通平衡树)

    划着划着水一不小心NOIP还考的凑合了… 所以退役的打算要稍微搁置一下了… 要准备准备省选了…. 但是自己已经啥也不会了… 所以只能重新拾起来… 从splay开始吧… splay我以前扔了个板子来着, ...

  4. 挖个坑,写一个Spring+SpringMVC+Mybatis的项目

    想挖个坑督促自己练技术,有时候想到一个项目,大概想了一些要实现的功能,怎么实现.现在觉得自己差不多能完成QQ空间的主要功能了.准备立个牌坊,写一个类似功能的网站.并且把进度放到这里来. 初步计划实现以 ...

  5. SSM久别遇新坑

    SSM久别遇新坑 久别个锤子,也就几天没看,改bug改到怀疑人生 maven的父子模块问题 众所周知,用maven建立一个空的模块,在它之下,将原本的各层次结构分别新建为一个子模块,就能够将各业务进行 ...

  6. 【repost】如何学好编程 (精挑细选编程教程,帮助现在在校学生学好编程,让你门找到编程的方向)四个方法总有一个学好编程的方法适合你

    方法(一)编了这么久的程序,一直想找机会总结下其中的心得和方法,但回想我这段编程道路,又很难说清楚,如果按照我走过的所有路来说,显然是不可能的!当我看完了云风的<游戏之旅--编程感悟>和梁 ...

  7. CC++初学者编程教程(9) Windows8.1安装VS2013并捆绑QT与编程助手

    我们在Windows8.1安装VS2013并捆绑QT与编程助手需要下列文件. 2. 在虚拟机中开启Windows8.1 3.然后选择VS2013的安装镜像. 4.将镜像复制到虚拟机. 5.我们装载这个 ...

  8. CC++刚開始学习的人编程教程(9) Windows8.1安装VS2013并捆绑QT与编程助手

    我们在Windows8.1安装VS2013并捆绑QT与编程助手须要下列文件. 2. 在虚拟机中开启Windows8.1 3.然后选择VS2013的安装镜像. 4.将镜像拷贝到虚拟机. 5.我们装载这个 ...

  9. 转 Oracle DBCA高级玩法:从模板选择、脚本调用到多租户

    但凡是学过Oracle的同学,对DBCA(Database Configuration Assistant, DBCA)都不会陌生,有了这个工具,使得创建数据库成为可能.而DBCA本身有图形和静默两种 ...

随机推荐

  1. C# checkboxlist的使用

    最近做项目,需要用到checklistbox这一控件,由于对这一控件并不是很熟悉,导致在此浪费了一点时间. http://www.cnblogs.com/hongfei/archive/2012/12 ...

  2. Python (1) - 7 Steps to Mastering Machine Learning With Python

    Step 1: Basic Python Skills install Anacondaincluding numpy, scikit-learn, and matplotlib Step 2: Fo ...

  3. 不错的TOMCAT监控好工具probe

    Tomcat版本:6.0.41 Probe版本:2.3.3 一,Tomcat没有默认用户账号,故首先需要添加Tomcat用户账号 修改$CATALINA_HOME/conf/tomcat-users. ...

  4. String课后作业

    请查看String.equals()方法的实现代码,注意学习其实现方法. public class StringEquals { @param args the command line argume ...

  5. HTTP 304

    304 的标准解释是:Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档).服务器告诉客户,原来缓冲的 ...

  6. Linux学习 : 裸板调试 之 配置使用NAND FLASH

    关于NAND FLASH的结构是以页为单位写,以块为单位来擦除: 1Gb     为大页   page=2048Kb    BLOCK=128K 512Mb 为小页   page=512byte   ...

  7. Android常见控件— — —ProgressBar

    ProgressBar用于在界面上显示一个进度条,表示我们的程序正在加载一些数据. <?xml version="1.0" encoding="utf-8" ...

  8. segues的类型

    Name Interface Builder symbol Description Show Present the content in the detail or master area depe ...

  9. OD调试篇13

    今天的程序比较大,听说还是比较牛的程序,不过破解它的一个比较老的版本的.打开程序看看. 点击about   然后点enter registration code    输入name  以及密钥之后,会 ...

  10. IOS7.0 Xcode5 AutoLayout 备忘录

    Xcode5 xib设置autolayout方式: 列表1: (选择两个view时可设置) 左边对齐, 右边对齐, 顶部对齐, 底部对齐, x轴中心对齐, y轴中心对齐, 文本底标线对齐, (单选择一 ...