开发者

Should names representing template types be a single character?

we're defining some C++ coding style guidelines based on these guidelines. Number 8 says "Names representing template types should be a single uppercase letter." Explanation: "Common practice in the C++ development community. This makes template names stand out relative to all other names used."

Is it really that common? I agree that it开发者_运维技巧 makes a lot of sense to have template<class T> class vector {...}. But what if I have several template Arguments? I don't think that <class A, class B> is easier to understand than <class AllocationPolicy, class ThreadingPolicy>.

Do you agree that there are often cases when the given rule should not be applied (which is allowed according to 1...)?

Thanks for you thoughts!


I don't really agree with that naming convention. For me, template parameters representing a fully generic type make sense as a simple letter --this is a type T, I don't really care which. But if there is any requirements on the type, it makes sense to produce a name that identifies what the template argument is: template <typename T, typename Allocator> struct container -- the first type is generic, any T will fit, but the second one is an allocator.

It is no different to functions, where you do not want your parameters to be called a, b... in order or appearance, but rather produce meaningful names as part of the documentation. Also, if developing a style guide, I would consider requiring local typedefs of the template arguments in the case of template classes together with static asserts on the requirements for the types (whenever possible). That is, at least until concepts provide that functionality.

I consider the STL to be a good example of library and you can see that generating typedefs help in reading the code (from g++ 4.2 stl):

Classes:

// 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() 

And functions:

template <typename _InputIterator, typename _Tp>
inline _InputIterator find( _InputIterator __first, _InputIterator __last, _Tp value ) {
  // concept requirements
  __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
  [...]

All of their names are prefixed by _ and either a capital letter or a second _, which are the names reserved for the implementation, and they prefer _Tp over _T, but at the end you can see that whenever a type is generic it is called _Tp, _Tp1..., while when it has some specific requirements attached, a more sensible name is chosen.

There is a fine line in between them, as for example in std::vector, there are actual requirements on the generic type: _Tp must be assignable, but at the end of the day, it is a mostly generic type. Calling it _Assignable would be weird in some containers where there are more than one requirement.


I guess it depends on how many parameters you have. If a parameter is a type and it's the only parameter why can't it just be T? However I agree with you that in case of multiple parameters they should have meaningful names for the same reason why variables should usually have meaningful names.


Certainly expressive names for template types are in order. It would be even more useful when, some day, concepts are introduced in the language (a pity they were dropped for the C++0x). In the mean time, the name of the template parameter type describes the expectation for that given type, at least informally (concepts would give them a formality, listing the expected types and operations the type must have).


Various coding standards will define different naming. Just pick one, and stick to it.

My preferences are to have descriptive names, and not some generic type name T (although it is not bad in some situations).


I think the main problem with single-letter names (in templates and otherwise) is when you want to do a search-and-replace. If your text editor doesn't include a C++ parser (and most don't), single-letter names will cause a lot of spurious matches that you didn't intend. With longer/descriptive names, OTOH, the search-and-replace is more likely to work as intended.


If it's just a type, I tend to use single-letter identifiers (T, U etc). If the argument has a special more limited meaning (predicate, allocator etc), I'd use something more descriptive.

However, single-letter identifiers (T) can back-fire, by colliding with macro names (see GCC 4.2 Template strange error), which is probably more unlikely with longer identifiers (if they don't use the same ALL_CAPS convention as macros).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜