学习C++设计新思维(泛型编程与设计模式之应用).pdf之继承关系检查

ok!主题是:检查型别A与B是不是有继承关系,在本书的P38,下面直接上代码。

#pragma once


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) };
	enum { exists2Ways = exists && Conversion<U, T>::exists };
	enum { sameType = false };
};

template<class T>
class Conversion < T, T >
{
public:
	enum { sameType = true, exists = true, exists2Ways = true };
};


#define SUPERSUBCLASS(T, U)	\
	(Conversion<const T*, const U*>::exists &&	\
	!Conversion<const T*, const void*>::sameType)



#define SUPERSUBCLASS_STRICT(T, U)	\
	(SUPERSUBCLASS(T, U) &&	\
	!Conversion<const T, const U>::sameType)

void chapter2_CI_CI()
{
	cout << "<int->long>" << Conversion<int, long>::exists << "\n" << endl;
	cout << "<char->char*>" << Conversion<char, char*>::exists << "\n" << endl;
	cout << "<std::size_t->vector<int>>" 
		<< Conversion<std::size_t, std::vector<int>>::exists << "\n" << endl;

	class A{};
	class B : public A{};
	cout << "SUPERSUBCLASS(A, B):" << SUPERSUBCLASS(A, B) << endl;
	cout << "SUPERSUBCLASS(B, A):" << SUPERSUBCLASS(B, A) << endl;
	cout << "SUPERSUBCLASS(int, long):" << SUPERSUBCLASS(int, long) << endl;
	cout << "SUPERSUBCLASS(int, int):" << SUPERSUBCLASS(int, int) << endl;
	cout << "SUPERSUBCLASS(char, char*):" << SUPERSUBCLASS(char, char*) << endl << endl;

	cout << "SUPERSUBCLASS_STRICT(A, B):" << SUPERSUBCLASS_STRICT(A, B) << endl;
	cout << "SUPERSUBCLASS_STRICT(B, A):" << SUPERSUBCLASS_STRICT(B, A) << endl;
	cout << "SUPERSUBCLASS_STRICT(int, long):" << SUPERSUBCLASS_STRICT(int, long) << endl;
	cout << "SUPERSUBCLASS_STRICT(int, int):" << SUPERSUBCLASS_STRICT(int, int) << endl;
	cout << "SUPERSUBCLASS_STRICT(char, char*):" << SUPERSUBCLASS_STRICT(char, char*) << endl;

}

<int->long>1
<char->char*>0
<std::size_t->vector<int>>0


SUPERSUBCLASS(A, B):0
SUPERSUBCLASS(B, A):1
SUPERSUBCLASS(int, long):0
SUPERSUBCLASS(int, int):1
SUPERSUBCLASS(char, char*):0


SUPERSUBCLASS_STRICT(A, B):0
SUPERSUBCLASS_STRICT(B, A):1
SUPERSUBCLASS_STRICT(int, long):0
SUPERSUBCLASS_STRICT(int, int):0
SUPERSUBCLASS_STRICT(char, char*):0
请按任意键继续. . .


上面是代码和运行结果。使用win7+vs2013.

----------------------

我也是才学模板的,所以涉及不深,也说不上什么来。错误之处请指正。

他的转换是依赖函数的重载机制的。

像代码:enum { exists = sizeof(Test(MakeT())) == sizeof(Small) };使用MakeT方法的返回值传给方法Test,而Test有2个版本,所以编译器择优选择,如果可以匹配到static Small Test(U),则可以转换,负责编译器只能选择static Big Test(...);,这时就表示不能转换,同时再依赖于sizeof的大小检测。这里应该都明白了, 但是看你会有一个问题,A不能转换为B,但是要是2个大小一样怎么办?请看: typedef char Small;class Big{ char dummy[2]; };


同时在检测类型一致时,使用了类模板偏特化的机制,函数是没有偏特化的。但是好像可以使用TYPE2TYPE来填坑。

类:

template<class T>
class Conversion < T, T >

这个类模板的声明呢,跟代码里其他一个模板类的声明不一样,一个是template<class T, class U>,一个就是template<class T>,但是这个类却使用了 class Conversion < T, T >,这个就是偏特化,如果你要定义一个类对象,如:Conversion (int ,int),那么编译器会选择模板参数只有一个的,如果你定义Conversion (int ,long),他会选择有两个模板参数的。模板偏特化还可以让你这么定义:

template<class T>
class Conversion < T, int >

这样不管T是什么,如果第二个参数是int,就会选择这个版本。

----------------------

不说了,免得误导人~~!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值