型别到型别的映射

变量,常数,类型在编译器看来可以分为两类,后两者是同一类的,原因是前者无法在编译期得知其确切的值。

对于判断语句,作用是在运行期选择不同的分支来运行。

那么在编译期选择不同的分支来运行用什么语句来做到呢?运行嘛,最终也要落在函数身上,不管是面向过程,还是面向对象都是如此,于是问题就划归成为在编译期选择不同的函数来运行。

使用常数来选择不同的函数,我想通过函数指针数组来实现是一种方法,但实在是不美观,不便捷;使用类型来选择不同的函数又该如何呢?

回答这个问题需要清楚不同的函数是什么意思,即确定一个函数函数的方法什么:1.函数名,2.函数输入参数。此时很容易想到的用类型来选择不同的函数的一个方法了:使用同名函数的重载。这的确是个好办法,先不说弊端,陈述型别到型别的映射的时候会说明:

//以下不同的类型拥有两种构造函数(许多的新类型都是采用的一个参数的构造函数)
//但是唯一的旧类型用了两个参数的构造函数
struct TypeOld
{
	template<class T>
	TypeOld(T, int){std::cout << "TypeOld被构造" << std::endl;}
};
struct TypeNew1
{
	template<class T>
	TypeNew1(T){std::cout << "TypeNew1被构造" << std::endl;}
};
struct TypeNew2
{
	template<class T>
	TypeNew2(T){std::cout << "TypeNew2被构造" << std::endl;}
};//还有很多新的类型,省略
//为新类型造就一个构造器
template<class In, class Out>
Out* Creator(const In& i)
{
	return new Out(i);
}
//旧类型也要使用同名的构造函数怎么办,下面这样做可以么
//不可以的,因为函数不支持偏特化
//error C2768: “Creator”: 非法使用显式模板参数
template<class In>
TypeOld* Creator<In, TypeOld>(const In& i)
{
	return new TypeOld(i, 0);
}

函数不支持模板偏特化,但是有近似的功能,函数重载,只可惜输出参数是不能参与重载决议的,所以要想办法让输出参数也进入输入参数中,以下是很容易想到的做法:

//那该怎么办,函数只能重载,在这个上想办法
//要重载就只能让Out参与输入参数
template<class In>
TypeOld* Creator(const In& i, TypeOld)
{
	return new TypeOld(i, 0);
}
//的确是重载了,但是Out如果是个很大的类,岂不是太浪费了,并且让输入参数的个数发生了变化

如果TypeOld是个构造复杂的类,这样太亏了,这也就是之前提到的重载弊端,于是编译期间型别到型别的映射的需求呼之欲出:

//首先解决Out这个白构造的输入参数,如果将这个类映射成为另一个(构造很便宜的)类就好了:
template<class T>
struct Type2Type
{
	//typedef T ValueType;
};
template<>
struct Type2Type<TypeOld>
{
	//typedef TypeOld ValueType;
};

然后利用这个映射过后的类来做重载操作:

template<class In, class Out>
Out* Creator(const In& i, Type2Type<Out>)
{
	return new Out(i);
}
template<class In>
TypeOld* Creator(const In& i, Type2Type<TypeOld>)
{
	return new TypeOld(i, 0);
}

这个类没有数据元素,因此构造他是不花费什么代价的,太好了,那么怎么会到当初的那个只有一个输入参数的函数接口呢?重载来了:

template<class In, class Out>//将这个重量级类Out
Out* CreatorNew(In i)
{
	return Creator(i, Type2Type<Out>()/*映射成为轻量级的Type2Type<Out>*/);
}

由于模板支持非类形参,所以常数也是可以映射为类型并利用重载在编译期做分支(不同的函数)的选择。

总结一下:

利用类型配合函数的重载可以在编译期实现条件分支语句,但是要牺牲输入参数的构造代价,恰好类型到类型的映射可以将这部分的代价降低到最小,如此的配合就完美了。

posted on 2011-03-17 15:14  Observer  阅读(283)  评论(0编辑  收藏  举报

导航