1 minute read

typename

当你在 template<class T> 的内部需要使用 T 的内部类时,需要使用 typename,比如:

template <class T>
void foo() {
	typename T::Iterator* iter; 	// Iterator 是 T 的内部类
	int size = T::DEFAULT_SIZE;		// DEFAULT_SIZE 是 T 的 static member
}

其实主要就是为了区分 T 内部类和 T 的 static member。

这篇 A Description of the C++ typename keyword 写得非常工整和详细,简单说就是:

  • std::cout 这样的 “全称” 我们称为 qualified name,意思是不受 scope 约束的 name
  • template<class T> 内部,T 是 dependent type (depending on a template parameter)
    • 不需要 parameter 指定的 type 称为 independent type
  • Before a qualified dependent type, you need typename

另外还有个额外的用法,就是 template<typename T> 等价于 template<class T>,从语义上说 typename 这个用词更准确。

template

Thinking in C++, Volume 2 书上的那个例子并不直观,还是 Where and why do I have to put the “template” and “typename” keywords? 这个帖子的例子举得好:

boost::function<int()> f;

这是 boost 库的一个 template,注意 int() 这里其实是一个 function 签名,并不是调用 int 构造器。

同样地,我们还可以写:

namespace boost { int function = 0; }
int main() { 
	int f = 0;
	boost::function<int()> f; 
}

最后一句的 int() 这里就会被解析为一个 int 构造器,所以这句就等价于 0 <0> 1,变成了一个合法的表达式!

实际应用中,如果编译器确定 boost::function 是一个 template 的话,它其实是不会犯错的,因为:

After name lookup finds that a name is a template-name, if this name is followed by a <, the < is always taken as the beginning of a template-argument-list and never as a name followed by the less-than operator

但是如果编译器不知道呢?(我猜一种可能的情形是:比如 template name 和某个变量同名?)这时我们就需要用 template 来指明 “这里是一个 template”。(这完全是将设计缺陷转嫁给消费者的行为!)

这种用法的 template 关键字只能出现在 after a ::, or after a -> or . in a class member access,比如:

t::template f<int>();		// call a function template
this->template f<int>();	// call a function template

Tags:

Categories:

Updated:

Comments