在C++中,各种数值类型的转化是C++编译过程中警告的主要来源,但是,很多时候,我们需要使用各种数值类型,例如我们用数组的某一位表示大小为对应序号的值,这种情况下,经常会涉及多种数值类型。根据C++ Programming Language中的建议,在数值类型转换时,使用narrow_cast来实现运行时安全,这里给出C++14版本的实现。

// there is no implicit conversion from Source to Target
template <typename Target, typename Source,
typename = std::enable_if_t<
!std::is_same<std::common_type_t<Target, Source>, std::decay_t<Target>>::value>>
inline Target narrow_cast(Source v)
{
static_assert(!std::is_reference<Target>::value, "The target couldn't be reference");
static_assert(std::is_arithmetic<Source>::value, "The parameter of narrow_cast should be arithmetic");
static_assert(std::is_arithmetic<Target>::value, "The return value of narrow_cast should be arithmetic"); // using Target_U = std::remove_reference_t<Target>;
// using Source_U = std::remove_reference_t<Source>; auto r = static_cast<Target>(v);
if (static_cast<Source>(r) != v)
throw std::runtime_error("narrow_cast<>() failed");
return r;
} // there is implicit conversion from Source to Target
template <typename Target, typename Source,
typename = std::enable_if_t<
std::is_same<std::common_type_t<Target, Source>, std::decay_t<Target>>::value>>
inline constexpr std::remove_reference_t<Source> narrow_cast(Source v)
{
static_assert(!std::is_reference<Target>::value, "The target couldn't be reference");
static_assert(std::is_arithmetic<Source>::value, "The parameter of narrow_cast should be arithmetic");
static_assert(std::is_arithmetic<Target>::value, "The return value of narrow_cast should be arithmetic"); return static_cast<Target>(v);
}

下面给出,使用Catch写的简单测试用例:

#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <cmath> TEST_CASE("Test narrow_cast", "[narrow_cast]")
{
int i = ;
long long j = ;
long long& k = j;
REQUIRE(narrow_cast<long>(k) == );
REQUIRE(narrow_cast<long>(i) == );
long long very_big = pow(, );
bool exception = false;
try
{
narrow_cast<long>(very_big) == very_big;
}
catch (const std::runtime_error& error)
{
exception = true;
}
REQUIRE(exception);
//REQUIRE(narrow_cast<long&>(k) == 15);
//REQUIRE(narrow_cast<long&>(i) == 10);
}

测试可知,在转化的类型可以容纳时,narrow_cast可以正常运行,如果narrow_cast转化后的值与原值不同时,会抛出runtime_error的异常。

C++ Programming Language中的narrow_cast实现的更多相关文章

  1. C++ Programming Language中的Calculator源代码

    C++ Programming Language 4th中的Calculator源代码整理,因为在C++ Programming Language中,涉及了很多文件位置之类的变化,所以,这里只是其中的 ...

  2. 编程提取字符串"Java is a programming language"中的各个单词,并打印输出。

    import java.lang.String; import java.util.StringTokenizer; public class StringGetWord{ /* 编程提取字符串&qu ...

  3. iOS Swift-元组tuples(The Swift Programming Language)

    iOS Swift-元组tuples(The Swift Programming Language) 什么是元组? 元组(tuples)是把多个值组合成一个复合值,元组内的值可以使任意类型,并不要求是 ...

  4. iOS Swift-控制流(The Swift Programming Language)

    iOS Swift-控制流(The Swift Programming Language) for-in 在Swift中for循环我们可以省略传统oc笨拙的条件和循环变量的括号,但是语句体的大括号使我 ...

  5. The Swift Programming Language 中文翻译版(个人翻新随时跟新)

    The Swift Programming Language --lkvt 本人在2014年6月3日(北京时间)凌晨起来通过网络观看2014年WWDC 苹果公司的发布会有iOS8以及OS X 10.1 ...

  6. [iOS翻译]《The Swift Programming Language》系列:Welcome to Swift-01

    注:CocoaChina翻译小组已着手此书及相关资料的翻译,楼主也加入了,多人协作后的完整译本将很快让大家看到. 翻译群:291864979,想加入的同学请进此群哦.(本系列不再更新,但协作翻译的进度 ...

  7. the C programming language 阅读笔记1

    读了一遍著名的<the C programming language>,果然如听说的一样,讲解基础透彻,案例简单典型,确实自己C语言还有很多细节点不是很清楚. 总结一下阅读的收获(部分原书 ...

  8. Introduction to OOC Programming Language

    Introduction to OOC Programming Language 文/akisann @ cnblogs.com / zhaihj @ github.com 本文同时发布在github ...

  9. 不忘初心 --- 重读<<The C Programming Language>>

    这篇文章应该发布在好几年前,2011年计算机界大师Dennis Ritchie仙逝,那时对大师的映象还停留在大一刚学编程时:Unix的合作开发者,C语言的发明人.通过网上的纪念文章<<Un ...

随机推荐

  1. mybatis_generator合并xml mapper文件

    一.问题 用的mybatis.generator 1.3.6版本,版本没啥大关系. 目前的xml输出有两个主要的问题: 1.xml追加而不是覆盖 这样就导致一个xml mapper文件每个node都重 ...

  2. Android设备终端监控可能用到的工具

    先记录工具,以后详细分析 add-property-tagcheck-lost+foundcpueatercpustatsdaemonizedexdumpdirectiotestfiokexecloa ...

  3. ES5和ES6那些你必须知道的事儿(一)

    ES5和ES6那些你必须知道的事儿 ES5新增的东西 一.数组方法 1.forEach     用途:遍历,循环 对于空数组不会执行回调函数 //用法 array.forEach( function( ...

  4. Python—列表操作

    列表 列表的使用: 列表是可变数据类型,因此列表的方法,都是直接修改列表原始值 list = ["panda","chimpanzee","zebra ...

  5. windows下《Go Web编程》之Go环境配置和安装

    <Go Web编程>笔者是基于unix下讲述的,作为入门练手,我选择在windows下开发,全程按照目录进行... 一.安装 windows下需要安装MinGW,通过MinGW安装gcc支 ...

  6. MVC跨域API

    API using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Ne ...

  7. mysql InnoDB index 主键采用聚簇索引,二级索引不采用聚簇索引

    原文链接 我的归纳: (1)InnoDB的主键采用聚簇索引存储,使用的是B+Tree作为索引结构,但是叶子节点存储的是索引值和数据本身(注意和MyISAM的不同). (2)InnoDB的二级索引不使用 ...

  8. ubuntu14.04安装 Apache2 并配置https

    一.安装 Apache2 sudo apt-get update sudo apt-get install apache2 安装完apache2,默认根目录在/var/www/html 下,点击其下的 ...

  9. JavaScript 简单的实现 sleep功能 .

    function start(){ // console.log("Request handle 'start' was called."); function sleep(mil ...

  10. Java学习笔记35(sql补充)

    在上一篇里,写了数据库的增删该查,没有写完,这里补充 CREATE DATABASE Zs_Base; USE Zs_Base; # 创建表 CREATE TABLE PRODUCT( ID INT ...