使用模板元在编译期间进行字节顺序的判断并且转换为相应字节顺序(大小端法转换)(原)
2012-12-15 00:09
260 查看
使用模板元在编译期间进行字节顺序的判断并且转换为相应字节顺序(大小端法转换)(原)
首先,开篇我先简单提提什么是模板元编程.模板元编程就是使用模板,在编译期间计算出一定的结果.例如我们在代码里面写有
可能大家都会写过这样的函数,在这个时候你会觉得与其fun(100,20)这样调用,不如直接写120,那肯定会让程序快点
但是,问题可能不会那么简单,例如你想在代码里面表达654M这个大小,但是你又不想写 685768704 这样一个奇怪的数字进去你的代码.
问题可能会比现在你所看到的或者想到的更加复杂.例如你想输入一个2维数组,然后累加里面所有的数,你总不可能去算吧?但是放在运行时计算也会让程序变慢,
这种一开始就能知道的值为什么我们不能在编译的时候算好呢?
模板元就能够达到这个效果.
对于刚刚那个简单的相加的函数,我们可以给出简单的模板元函数
看,这样就可以很优雅地预先算好这个值
好了,下面开始正题.解释我都写在代码里面的注释里,下面上代码
模板元非常忠实地帮我们计算出结果,善用模板元将会在大工程里面对我们有很大帮助.
首先,开篇我先简单提提什么是模板元编程.模板元编程就是使用模板,在编译期间计算出一定的结果.例如我们在代码里面写有
int fun(int x,int y){ return x + y; } assert(fun(100, 20) == 120);
可能大家都会写过这样的函数,在这个时候你会觉得与其fun(100,20)这样调用,不如直接写120,那肯定会让程序快点
但是,问题可能不会那么简单,例如你想在代码里面表达654M这个大小,但是你又不想写 685768704 这样一个奇怪的数字进去你的代码.
问题可能会比现在你所看到的或者想到的更加复杂.例如你想输入一个2维数组,然后累加里面所有的数,你总不可能去算吧?但是放在运行时计算也会让程序变慢,
这种一开始就能知道的值为什么我们不能在编译的时候算好呢?
模板元就能够达到这个效果.
对于刚刚那个简单的相加的函数,我们可以给出简单的模板元函数
template<int x, int y> struct fun{ const static int _ret_val = x + y; } assert(fun<100, 20>::_ret_val == 120);
看,这样就可以很优雅地预先算好这个值
好了,下面开始正题.解释我都写在代码里面的注释里,下面上代码
// Copyright (C) 2012/12/15 fish // // // #ifndef _FISH_ENDIAN_H_ #define _FISH_ENDIAN_H_ #ifdef _MSC_VER #define IS_BIG_ENDIAN false //#elif //这里定义其他平台 //本人对除windows平台以外的平台不熟悉 //望有心人看到帮忙补充 //谢谢 #endif struct check_endian{ const static bool _is_big_endian = IS_BIG_ENDIAN; const static bool _is_little_endian = !IS_BIG_ENDIAN; }; //字节顺序转换模板函数 template<unsigned int i> struct _change_endian{ //分别取出1,2,3,4个字节,然后交换 const static unsigned int _i1 = i >> 24; const static unsigned int _i2 = ((i << 8) >> 24) << 8; const static unsigned int _i3 = ((i << 16) >> 24) << 16; const static unsigned int _i4 = (i << 24); const static unsigned int _ret_val = _i1 + _i2 + _i3 + _i4; }; ////////////////////////////////////////////////////////////////////////// //转换为小端法 //其中有默认模板参数,使用了check_endian判断是哪种字节顺序 template<unsigned int i, bool _is_little_endian = check_endian::_is_little_endian> struct to_little_endian_int32{ }; //发现本平台已经是小端法则什么也不做返回 template<unsigned int i> struct to_little_endian_int32<i, true>{ const static unsigned int _ret_val = i; }; //否则调用_change_endian转换字节顺序 template<unsigned int i> struct to_little_endian_int32<i, false>{ const static unsigned int _ret_val = _change_endian<i>::_ret_val; }; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// //转换为大端法 template<unsigned int i, bool _is_big_endian = check_endian::_is_big_endian> struct to_big_endian_int32{ }; //发现本平台已经是大端法则什么也不做返回 template<unsigned int i> struct to_big_endian_int32<i, true>{ const static unsigned int _ret_val = i; }; //否则调用_change_endian转换字节顺序 template<unsigned int i> struct to_big_endian_int32<i, false>{ const static unsigned int _ret_val = _change_endian<i>::_ret_val; }; ////////////////////////////////////////////////////////////////////////// #endif //_FISH_ENDIAN_H_
模板元非常忠实地帮我们计算出结果,善用模板元将会在大工程里面对我们有很大帮助.
相关文章推荐
- 判断日期格式并且进行相应合法格式的转换
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
- 水晶报表使用经验谈1--建立水晶报表第一步及编译最易出现错误的解决方法及报表转换成pdf文档进行打印方法
- 使用Oracle可传输表空间的特性复制数据(4)转换字节顺序
- 写几个带继承关系的类,使用直接强转的方式,以及使用as转换, 并且练习is的类型判断
- error C1128:字节数超过对象文件格式main.cpp限制:请使用/bigobj进行编译
- C++模板元编程之使用模板,对数组进行“编译期间求和”
- 使用时间控件,并且比较时间大小,和时间类型之间的转换
- WPF备忘录(3)如何从 Datagrid 中获得单元格的内容与 使用值转换器进行绑定数据的转换IValueConverter
- 回发或回调参数无效。在配置中使用 或在页面中使用 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。
- [置顶] 简述如何嵌套使用Viewpager,点击图片放大查看图片,并且使用PhotoView进行图片处理
- Linux下使用RecordMyDesktop进行屏幕录像 输出图像格式转换
- [编译原理代码][NFA转DFA并最小化DFA并使用DFA进行词法分析]
- js判断复选框,是单选还是多选,并且执行相应的事件
- STM32F1xx 多路ADC 使用DMA转换结果顺序错乱问题
- 使用json-lib进行Java和JSON之间的转换
- 程序猿之---C语言细节16(看了绝对值,编译类型ANSI C和K&R C类型判断,c编译器类型转换bug的细节)
- 23.2.2 使用bool类型进行判断
- 使用跟踪和调试进行条件编译
- LINUX下QT FOR ARM开发环境搭建过程 (使用qt-x11-opensource-src-4.5.2.tar.gz进行编译)