函数作为模板参数
众所周知,模板参数可以是特定的整数也可以是特定的函数。这使得编译器在实例化模板代码时内联调用特定的函数以获得更高效的执行。下面的例子里,函数memoize的模板参数也是一个函数且只有新的参数值才通过函数调用(旧的参数值可以通过cache获得):
#include
template
intmemoize(intx) {
staticstd::map cache;
std::map::iterator y = cache.find(x);
if(y != cache.end())returny->second;
returncache[x] = f(x);
}
intfib(intn) {
if(n
returnmemoize(n - 1) + memoize(n - 2);
}
模板的参数也是模板
模板参数实际上自身的参数也可以是模板,这可以让你在实例化一个模板时可以不用模板参数就能够传递模板类型。看下面的代码:
template
structCache { ... };
template
structNetworkStore { ... };
template
structMemoryStore { ... };
template
structCachedStore {
Store store;
Cache cache;
};
CachedStore,int> a;
CachedStore,int> b;
CachedStore的cache存储的数据类型与store的类型相同。然而我们在实例化一个CachedStore必须重复写数据类型(上面的代码 是int型),store本身要写,CachedStore也要写,关键是我们这并不能保证两者的数据类型是一致的。我们真的只想要确定数据类型一次即 可,所以我们可以强制其不变,但是没有类型参数的列表会引起编译出错:
// 下面编译通不过,因为NetworkStore和MemoryStore缺失类型参数
CachedStore c;
CachedStore d;
模板的模板参数可以让我们获得想要的语法。注意你必须使用class关键字作为模板参数(他们自身的参数也是模板)
templateclassStore,typenameT>
structCachedStore2 {
Store store;
Cache cache;
};
CachedStore2 e;
CachedStore2 f;
try块作为函数
函数的try块会在检查构造函数的初始化列表时捕获抛出的异常。你不能在初始化列表的周围加上try-catch块,因为其只能出现在函数体外。为了解决这个问题,C++允许try-catch块也可作为函数体:
intf() {throw0; }
// 这里没有办法捕获由f()抛出的异常
structA {
inta;
A::A() : a(f()) {}
};
// 如果try-catch块被用作函数体并且初始化列表移至try关键字之后的话,
// 那么由f()抛出的异常就可以捕获到
structB {
intb;
B::B() try: b(f()) {
} catch(inte) {
}
};
奇怪的是,这种语法不仅仅局限于构造函数,也可用于其他的所有函数定义。
【编辑推荐】
【责任编辑:chensf TEL:(010)68476606】