挺拗口的,不过TTP其实只是模板参数的进一步抽象。就像指针,指向指针的指针那样,这个比喻可能不太恰当,不过大概是这个意思啦。 下面的代码定义了一个模板类,第一个模板参数是接受类型的参数,第二个是接受模板类型的参数。 template < typename T, template < typename ELEM > class CONT = std::deque > class Stack { private : CONT < T > elems; public : } ; 单独将第二个参数提取出来看,template <> class CONT 只是一个很平常的模板,这便是定义一个模板类型的模板参数的语法,因为只是为了说明CONT是个模板,所以ELEM可以省去,即template class CONT,就算加上了,ELEM也不能当作类型使用,这实际上是一个dummy参数。有人要问了,typename能省吗?这可不行,template<> class CONT是实例化的模板,template class CONT是模板定义,两者不同。所以啦,为了让std::deque 参数能直接写成std::deque,绕了这么一大圈。 虽然typename与class在template参数定义中常常等价, 但是template class CONT = std::deque> 是有效的, 而template typename CONT = std::deque>是无效的,会引起编译错误。 为什么呢?因为CONT被定义为模板,而模板需要实例化才能使用,即CONT 。这么用的多半是class,而且我们在Stack定义中也是这么实现的,如此一来,typename便使得类型匹配处引起编译错误了,虽然不知道是否会出现可以使用typename的情况,书中确实提到Template template parameters for function templates are not allowed,看起来似乎只能使用class关键字。 不过上面的代码在使用时仍然不能通过编译,因为TTP的类型匹配不会使用默认参数,因此,对标准库的deque而言,第二个带默认值的参数alloca
Sail on this course and take it when it comes.