C++模版编程
浅式实例化
如果错误是在经过很长的实例化链表之后才被发现的,那么将会出现诸如前面所有讨论那些诊断信息。为了说明这个问题,先考虑下面我们自己写的代码。
#include <iostream>
template<typename T>
void clear(T const &p)
{
*p = 0;// P is a pointer
}
template<typename T>
void core(T const &p)
{
clear(p);
}
template <typename T>
void middle(typename T::Index p)
{
core(p);
}
template<typename T>
void shell(T const &env)
{
typename T::Index i;
middle<T>(i);
}
class client
{
public:
typedef int Index;
};
client main_client;
int main()
{
shell(main_client);
}
这个例子给出了软件开发中典型的层次结构,如shell()的高层函数模版依赖于诸如miidle()的组件,
而组件又使用了诸如core()的功能,当我们实例化shell()的时候,它下面层次的函数模版也应该相应的被实例化,在这个例子中,我们在最底层发现了一个问题,我们用int类型对core进行实例化,int来自于miidle中的Client::Index的使用,并且试图对一个int类型的值解引用,而这明显是错误的,另外,一分完整的通用诊断信息应该包含对产生这个问题的所有层次的跟踪信息,但是我们往往会发现根本很难准确的把握这么多信息。
我们将在13.11 节对前一种方法进行介绍,而后一种方法主要在于吧模版错误强制的浅式实例化中,我们是通过插入没有倍使用的代码,来获取这种实现的。这些代码并没有其他的用途,只是在实例化模版代码的高层次模版实参数不符合低层次模版约束时,引发一个错误。
在我们例子中,我们可以在shell中添加代码,试图对T::Index类型的值进行解引用,例如:
template<typename T>
Inline void ignore(T const &)
{}
Template <typename T>
Void shell(T const &env)
{
Class Shallow(T::Index ptr) {
void deref(T::Index ptr) {
ignore(*ptr);
}
};
Typename T::Index I;
middle(i);
}
如果T是一个使T::Index 不能被解引用的类型,那么在局部类ShallowChecks将会引发一个错误,另外我么知道,实际上这个局部类并没有被使用,因此添加的代码并不会影响shell 函数的运行时间,但是遗憾的是,许多编译器都会对ShallowChecks 并没有被使用这个事实提出警告,我们可以使用诸如ignore()模版等tricks 来避免这类警告,但是却会增加代码的复杂度。
编译提示
deep.cpp: In instantiation of ‘void clear(const T&) [with T = int]’:
deep.cpp:12:10: required from ‘void core(const T&) [with T = int]’
deep.cpp:18:9: required from ‘void middle(typename T::Index) [with T = client; typename T::Index = int]’
deep.cpp:25:14: required from ‘void shell(const T&) [with T = client]’
deep.cpp:38:22: required from here
deep.cpp:6:4:error: invalid type argument of unary ‘*’ (have ‘int’)
*p = 0;// P is a pointer
^~