技术之编译器检查

编译器检查

特点:

  1. 静态类型检查
  2. 可定制类型错误消息

例子:实现安全转型的函数,并确保较大型别不能转换成较小型别。
迭代一

template <typename To, typename From>
To safe_reinterpret_cast(From from)
{
	assert(sizeof(From) < sizeof(To));
	return reinterpret_cast<To>(from) ;
}

上述代码,会在执行期进行断言。
迭代二 期待编译期识别出错误,利用编译器做类型安全检查
方案一:
利用基本语法规则:大小为零的数组是非法的。

#define STATIC_ASSERT(expr) { char unnamed[(expr) ? 1 : 0]; }

template <typename To, typename From>
To safe_reinterpret_cast(From from)
{
	STATIC_ASSERT(sizeof(From) < sizeof(To));
	return reinterpret_cast<To>(from) ;
}

如果尝试将int*类型转换成char类型,书上说编译器将抱怨“正试着产生一个长度为零的数组”。

int* i = new int(100);
char ch = safe_reinterpret_cast<char>(i);

但新的编译器已经能完全给出更加易理解的信息:

<source>: In instantiation of 'To safe_reinterpret_cast(From) [with To = char; From = int*]':
<source>:21:40:   required from here
<source>:14:9: error: cast from 'int*' to 'char' loses precision [-fpermissive]
  return reinterpret_cast<To>(from) ;

方案二
利用模板特化,提供带有特定意义的 template类型名称,出错时编译器能打印出template类型名称。

template<bool> struct CompileTimeError;
template<> struct CompileTimeError<true> { };
#define STATIC_ASSERT(expr) (CompileTimeError<(expr)>())

上面使用,编译失败信息如下:

<source>:10:30: error: invalid use of incomplete type 'struct CompileTimeError<false>'
 #define STATIC_ASSERT(expr) (CompileTimeError<(expr)>())
                             ~^~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:15:2: note: in expansion of macro 'STATIC_ASSERT'
  STATIC_ASSERT(sizeof(From) < sizeof(To));
  ^~~~~~~~~~~~~
<source>:8:23: note: declaration of 'struct CompileTimeError<false>'
 template<bool> struct CompileTimeError;

从上述错误提示信息看出,CompileTimeError提示还没有表示出具体的意义。
迭代三 改良错误提示信息

template<bool> 
struct CompileTimeChecker
{
	CompileTimeChecker( ...);
};

template<> 
struct CompileTimeChecker<false> 
{};
#define STATIC_ASSERT(expr, msg) \
{ \
	 class ERROR_##msg{}; \
  (void)sizeof(CompileTimeChecker<(expr)>(ERROR_##msg( ))); \
}

template <typename To, typename From>
To safe_reinterpret_cast(From from)
{
	STATIC_ASSERT(sizeof(From) < sizeof(To), destination_type_too_narrow);
	return reinterpret_cast<To>(from);
}

上例中编译出错提示信息:

<source>:27:2: note: in expansion of macro 'STATIC_ASSERT'
  STATIC_ASSERT(sizeof(From) < sizeof(To), destination_type_too_narrow);

能明确提示具体错误原因。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值