我不太同意这种命名约定。对我来说,代表一个完全通用类型的模板参数作为一个简单的字母是有意义的——这是一个类型T,我真的不在乎哪个。但是如果对类型有任何要求,生成一个标识模板参数是什么的名称是有意义的:template <typename T, typename Allocator> struct container——第一个类型是通用的,任何T 都适合,但第二个是分配器.
这与函数没有什么不同,你不希望你的参数被称为a、b... 按顺序或外观,而是生成有意义的名称作为文档的一部分时间>。此外,如果开发样式指南,我会考虑在模板类的情况下要求模板参数的本地 typedef 以及对类型要求的静态断言(尽可能)。也就是说,至少在 概念 提供该功能之前。
我认为 STL 是一个很好的库示例,您可以看到生成 typedef 有助于阅读代码(来自 g++ 4.2 stl):
类:
// from <vector> -> <bits/stl_vector.h>
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class vector : protected _Vector_base<_Tp, _Alloc>
{
// Concept requirements.
typedef typename _Alloc::value_type _Alloc_value_type; // _Alloc contains value_type internal type
__glibcxx_class_requires(_Tp, _SGIAssignableConcept) // _Tp is assignable
[...]
public:
typedef _Tp value_type; // from here on _Tp is not mentioned
typedef typename _Tp_alloc_type::reference reference; // check + typedef
[...]
iterator begin() {
// without typedef:
// __gnu_cxx::__normal_iterator<pointer, vector_type> begin() {
[...]
reference operator[](size_type __n)
// _Tp& operator[](size_type __n)
[...]
// from <memory>
template <typename _Tp>
class auto_ptr
{
[...]
template <typename _Tp1>
auto_ptr(auto_ptr<_Tp1>& __a) throw()
和功能:
template <typename _InputIterator, typename _Tp>
inline _InputIterator find( _InputIterator __first, _InputIterator __last, _Tp value ) {
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
[...]
他们所有的名字都以_为前缀,或者是一个大写字母或第二个_,这是为实现保留的名字,他们更喜欢_Tp而不是_T,但最后你可以看到,当一个类型是generic时,它被称为_Tp、_Tp1...,而当它附加一些特定要求时,选择一个更合理的名称。
它们之间有一条细线,例如在std::vector 中,对泛型类型有实际要求:_Tp 必须是可赋值的,但归根结底,它是一个 主要是泛型类型。在一些有多个要求的容器中,将其称为 _Assignable 会很奇怪。