tommy
It's hard to tell the world we live in is either a reality or a dream
posts - 52, comments - 17, trackbacks - 0, articles - 0
C++博客
::
首页
::
新随笔
::
联系
::
聚合
::
管理
读书笔记《C++设计新思维》(5) 编译期间侦测可转换性
Posted on 2006-02-05 05:34
Tommy Liang
阅读(755)
评论(2)
编辑
收藏
引用
所属分类:
泛型编程与设计模式
就是这样一个类:
template
<
class
T,
class
U
>
class
Conversion
{
typedef
char
Small;
class
Big
{
char
dummy[
2
]; }
;
static
Small Test(U);
static
Big Test(
);
static
T MakeT();
public
:
enum
{ exists
=
sizeof
(Test(MakeT()))
==
sizeof
(Small) }
;
}
;
关于函数 Small Test(U) 和 Big Test(...) ,书里面说:
。。。需要两个重载函数,其一如先前所说,接受一个U对象并传回一个Small对象:
Small Test(U);
但接下来,我该如何写出一个可接受任何其他种对象的函数呢?。。。。
我觉得这个地方翻译得有点问题,是不是应该说:“。。我该如何写出一个可接受任何
另外一种类型(即 T)的
对象的函数呢。。”,因为这里就是 T和U嘛, 没有什么“其他种”,这样翻译容易让我迷惑不解了一会儿。
如果接受 U的那个函数被调用,则T可以被转换为 U,否则无法转换,这个是思路的根本。
为什么要做一个 MakeT这样的函数而不直接使用T呢? 这是为了满足当 T 只有私有构造函数的情况,对于编译器来说,sizeof 是在编译期完成评估的,所以,MakeT 里面到底做了什么并不重要,重要的是他返回的类型,是 T,所以,作者很兴奋地说,这是一个 StrawMan function,即“稻草人函数”,哈哈,只是一个样子而已,但是这已经足够了,那两个重载的Test方法也是一样,这里我们不关心他的函数体。强啊,爽歪歪,快感的源泉啊
测试代码如下:
using
namespace
std;
cout
<<
Conversion
<
double
,
int
>
::exists
<<
'
'
<<
Conversion
<
char
,
char
*>
::exists
<<
'
'
<<
Conversion
<
size_t, vector
<
int
>
>
::exists
<<
'
'
;
输出: 1 0 0
double可以转换为 int
char 不能转换为 char*
vector<int> 是一个容器的构造函数,size_t 不能转换,因为这个构造函数是 explicit的,这个地方还是有点迷糊,还得研究一下。
Feedback
#
re: 读书笔记《C++设计新思维》(5) 编译期间侦测可转换性
回复
更多评论
2006-10-10 15:37 by
wanglile
exists = sizeof(Test(MakeT())) == sizeof(Small)
这句,是不是说Test(...)这种函数的优先级是低于类型转换,所以如果T可以转换为U类型那Test(...)就变成调用Test(U),于是exists就是true,说明T和可以相互转换。
#
re: 读书笔记《C++设计新思维》(5) 编译期间侦测可转换性
回复
更多评论
2006-10-11 05:22 by
tommy
这是编译时逻辑,不是运行时逻辑。
enum { exists = sizeof(Test(MakeT())) == sizeof(Small) };
编译器根据程序中的代码调用状况,决定应该如何编译template相关的代码,
在编译时刻Conversion<T, U>::exists的值就计算出来了,
首先,sizeof(Small) 等于 1,
如果T就是U,或者T可以转换成U类型(这个就是关键),那么 Test(T) 就是Test(U),sizeof就等于sizeof(Small),恒等,意思是
Conversion<T,T>::exists一定是true,类型总是可以转换成自己。
如果T不是U,并且T不能转换成U类型,那么static Big Test(...)会被编译器“调用”(权且用这个词,编译原理只学了半桶水,不能装懂)
,因而exists就是false了(sizeof(Big)!=sizeof(Small),因为2!=1)。
之所以用MakeT这个函数,如作者所说,是为了满足当 T 只有私有构造函数的情况,编译器会在编译时检查语言的封装逻辑是否被违反,如果
存在违反情况将出现编译错误,MakeT这个函数就是为了绕过这个检查而设的,
我的理解是:用于运行时的代码中也没有“调用”这个函数,因而MakeT没有函数体也不会引起连接错误,就是编译通过了。
刷新评论列表
只有注册用户
登录
后才能发表评论。
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
相关文章:
递归数查寻表
读书笔记《C++设计新思维》(8) 边界标记:NullType和EmptyType
读书笔记《C++设计新思维》(7) std::type_info类的包装类
读书笔记《C++设计新思维》(6) 编译期间侦测继承性
读书笔记《C++设计新思维》(5) 编译期间侦测可转换性
读书笔记《C++设计新思维》(4) Type Selection
读书笔记《C++设计新思维》(3) Type2Type的意义
读书笔记《C++设计新思维》(2) Int2Type的意义
读书笔记《C++设计新思维》(1) Template Template 参数
网站导航:
博客园
IT新闻
BlogJava
知识库
博问
管理
Powered by:
C++博客
Copyright © Tommy Liang
日历
<
2006年4月
>
日
一
二
三
四
五
六
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
常用链接
我的随笔
我的评论
我参与的随笔
留言簿
(5)
给我留言
查看公开留言
查看私人留言
随笔分类
away3d(2)
C++语言与规范(5)
development idea(2)
Unix(1)
读书笔记《C++图算法》(3)
泛型编程与设计模式(9)
机器人(1)
进程与线程(3)
数学(2)
随笔档案
2015年1月 (1)
2013年8月 (1)
2013年1月 (1)
2012年12月 (1)
2012年5月 (1)
2012年4月 (1)
2012年3月 (1)
2011年11月 (3)
2011年6月 (3)
2011年5月 (1)
2011年3月 (2)
2011年1月 (1)
2010年10月 (1)
2010年9月 (5)
2009年7月 (3)
2009年3月 (2)
2006年4月 (3)
2006年2月 (9)
2006年1月 (2)
2005年12月 (7)
2005年10月 (3)
搜索
最新评论
1. re: 读书笔记《C++设计新思维》(3) Type2Type的意义
这2个有什么不同呢。
开销估计也差不多。
我觉得2者可能的不同还是在可扩展性上面。
--kaso
2. re: 邻接表 SparseMultiGRAPH
remove好像不太对吧,我们只是删一条边,你的删了很多呀
--windward
3. re: 最简单的堆栈溢出demo
在哪儿有个/gz 啊大哥
--石头儿
4. re: 最简单的堆栈溢出demo
int *eip = (int*)&hackstr[24]; //20->23是EBP
这一行中的[24]应该改成[20]吧,我是arm指令
--nuke
5. re: 关于C++的 explicit关键字
透彻,明白了
--一样一样
阅读排行榜
1. 关于C++的 explicit关键字(9992)
2. 四元数入门(8520)
3. 读书笔记《C++设计新思维》(7) std::type_info类的包装类(4061)
4. 最简单的堆栈溢出demo(2649)
5. Qt moc 的一个诡异提示(2299)
评论排行榜
1. 关于C++的 explicit关键字(6)
2. 最简单的堆栈溢出demo(4)
3. 读书笔记《C++设计新思维》(1) Template Template 参数(2)
4. 读书笔记《C++设计新思维》(5) 编译期间侦测可转换性(2)
5. 计时辅助类(1)