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. java 自带md5加密

    package test; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; pub ...

  2. jQuery绑定以及解除时间方法总结,以及事件触发的方法

     一   off()和on()          $("obj").on(event,[sesect],[data],fn);一般情况下参数只有两个,事件以及事件的处理函数     ...

  3. OrCAD搭建Access数据库

    刚进入到一个小公司,接到的第一个电路设计的案子是从零开始的,辛苦就不说,关键是这么不严谨,容易出错,于是乎,问题来了,能否从零开始着手建立个类似于以前公司的数据库,管理原理图封装,PCB封装及规格书! ...

  4. Cfree

    #include<stdio.h>int main(){ printf("Hello World!!!/n"); return 0;} #include<stdi ...

  5. html之小积累-.-iframe自适应高度

    在做系统框架的时候,常常会用到iframe,当需求是iframe不能出现纵向滚动条,需要根据加载页面的高度,一致延伸,但是iframe的高度自适应问题比较麻烦,当时也是纠结了好久. 方案1:当遇到if ...

  6. Windows 下字节转换

    Windows 下字节转换 #include <string> #include <windows.h> class CharsConversion { public: sta ...

  7. 2016HUAS_ACM暑假集训2G - Who's in the Middle

    这个题真的没什么好说的.一个排序就能解决的问题.唯一感到不爽的是这道题不是0msAC的,希望各位大神能够给我点指导. 头文件#include<algorithm>,注意一下排序函数的用法就 ...

  8. IIS-反向代理

    测试环境:Windows10.IIS/10.0 1.安装ARR.URL Rewrite(URL重写工具2.0) 注意英文和中文环境的对应: Application Request Routing 对应 ...

  9. 利用css3新增选择器制作背景切换

    之前写css3的时间都是捡项目需要的来用,没有系统的学习过,这几天好好的补了一下css3的知识,真的获益匪浅!觉得新增的那些选择器是有用至极的!今天就来所这几天的所学做一个点击标签切换背景的效果,是纯 ...

  10. fatal error: Invalid layout of preloaded class

    今天很奇怪,在java类中写一个单纯的main函数,打印一句话竟然出不来,后来各种资料找,终于知道解决的方法了,如下 错误截图: 解决方法: (1)选中你要运行的那个类,点击上方的project--p ...