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. 【代码】verilog之:电子钟

    功能:显示时分秒,能够设置时间. 实现:两个按键,一个进入设置,一个加数字.显示用LCD5110 用状态机实现,总共四种状态 idle(正常运行)——s_hour(时设置状态)——s_min(分设置状 ...

  2. POJ 2226 最小点覆盖(经典建图)

    Muddy Fields Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8881   Accepted: 3300 Desc ...

  3. UITableView编辑

      UITableView 编辑步骤如下: 1.让TableView处于编辑状态 2.协议设定  2.1.确定Cell是否处于编辑状态  2.2.设定Cell的编辑样式(删除.添加)  2.3.编辑状 ...

  4. 微信JS-SDK DEMO页面和示例代码

    <?php require_once "jssdk.php"; $jssdk = new JSSDK("yourAppID", "yourApp ...

  5. Linux I2C总线控制器驱动(S3C2440)

    s3c2440的i2c控制器驱动(精简DIY),直接上代码,注释很详细: #include <linux/kernel.h> #include <linux/module.h> ...

  6. C# WinForm控件之Dock顺序调整

    最近被.net winform中的控件布局搞困惑了,由于控件都是使用Dock方式的,操作起来也是比较方便,如果最大化,窗口大小调整等,都可以随着窗口大小的变化而变化. 但问题是,.net winfor ...

  7. 银光类似web visio的节点连线控件Essential Diagram免费下载地址

    Essential Diagram for Silverlight是一款功能强大的图解拓扑图控件,在XAML支持的情况下提供用户交互式地创建和编辑图解,支持数据绑定和多种布局,可以导出为多种文件格式等 ...

  8. PHP Html5上传大文件

    html前台代码: <form id="upload_form" name="upload_form" action="javascript:i ...

  9. 根据滑动显隐状态栏的iOS实现

    之前很多兄弟问如何实现类似于淘宝客户端搜索列表那种动态显隐的效果,这几天刚好有时间,就实现了几个例子搞一下,其实原理很简单,也参考了github上一位兄弟的实现.不多说,上代码 @interface ...

  10. mm/swap

    /* *  linux/mm/swap.c * *  Copyright (C) 1991, 1992  Linus Torvalds */ /* * This file should contain ...