2010-11-11 819 views
5

estamos definiendo algunas pautas de estilo de codificación C++ basadas en these guidelines. El número 8 dice "Los nombres que representan los tipos de plantilla deben ser una sola letra mayúscula". Explicación: "Práctica común en la comunidad de desarrollo C++. Esto hace que los nombres de las plantillas se destaquen en relación con todos los demás nombres utilizados".¿Los nombres que representan tipos de plantilla deben tener un solo carácter?

¿Es realmente así de común? Estoy de acuerdo en que tiene mucho sentido tener template<class T> class vector {...}. Pero, ¿y si tengo varios argumentos de plantilla? No creo que <class A, class B> sea más fácil de entender que <class AllocationPolicy, class ThreadingPolicy>.

¿Está de acuerdo en que a menudo hay casos en los que no se debe aplicar la regla dada (que está permitida según 1 ...)?

Gracias por tus pensamientos!

Respuesta

7

Realmente no estoy de acuerdo con esa convención de nomenclatura. Para mí, los parámetros de la plantilla que representan un tipo completamente genérico tienen sentido como una simple letra; este es un tipo T, realmente no me importa cuál. Pero si hay algún requisito sobre el tipo, tiene sentido producir un nombre que identifique cuál es el argumento de la plantilla: template <typename T, typename Allocator> struct container - el primer tipo es genérico, cualquier T encajará, pero el segundo es un asignador.

no es diferente a las funciones, en las que no desea que sus parámetros a ser llamado a, b ... con el fin o la apariencia, sino más bien producen nombres significativos como parte de la documentación . Además, si estoy desarrollando una guía de estilo, consideraría la necesidad de exigir los tipos locales de los argumentos de la plantilla en el caso de las clases de plantilla junto con las afirmaciones estáticas sobre los requisitos para los tipos (siempre que sea posible). Es decir, al menos hasta que conceptos proporcionan esa funcionalidad.

Considero que el STL es un buen ejemplo de biblioteca y se puede ver que la generación de typedefs ayuda a leer el código (desde g ++ 4.2 STL):

Clases:

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

y funciones:

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

todos sus nombres llevan el prefijo _ y, o bien una letra mayúscula o una segunda _, que son los nombres reservados para la implementación, y prefieren _Tp sobre _T, pero al final se puede ver que cada vez que un tipo es genérico se llama _Tp , _Tp1 ..., mientras que cuando tiene algunos requisitos específicos adjuntos, se elige un nombre más sensato.

Hay una fina línea entre ellos, como por ejemplo en std::vector, existen requisitos reales en el tipo genérico: _Tp debe poder asignar, pero al final del día, es un tipo genérico mayoría. Llamarlo _Assignable sería extraño en algunos contenedores donde hay más de un requisito.

+0

Como escribió '_' o' __ * 'están reservados para la implementación (en ciertos ámbitos), en mi humilde opinión, es mejor evitar el uso de cualquier identificador así nombrado (aunque probablemente no hará ningún daño en práctica). –

4

Supongo que depende de la cantidad de parámetros que tenga. Si un parámetro es un tipo y es el único parámetro, ¿por qué no puede ser solo T? Sin embargo, estoy de acuerdo con usted en que, en el caso de múltiples parámetros, deberían tener nombres significativos por la misma razón por la cual las variables generalmente deberían tener nombres significativos.

+2

Para mí, depende más de lo que representa cada argumento que de si hay más de un argumento: 'template struct pair' es un enfoque completo, mientras' template class vector' is * missing * que 'U' debe ser un asignador, no un tipo genérico. –

1

Definitivamente nombres expresivos para los tipos de plantilla están en orden. Sería aún más útil cuando, algún día, se introdujeran conceptos en el lenguaje (una pena que se descartaran para el C++ 0x). Mientras tanto, el nombre del tipo de parámetro de la plantilla describe la expectativa para ese tipo dado, al menos informalmente (los conceptos les darían una formalidad, enumerando los tipos esperados y las operaciones que el tipo debe tener).

1

Varios estándares de codificación definirán nombres diferentes. Solo elige uno y mantente firme.

Mis preferencias son tener nombres descriptivos, y no un nombre de tipo genérico T (aunque no está mal en algunas situaciones).

1

Creo que el principal problema con los nombres de una sola letra (en plantillas y demás) es cuando desea hacer una búsqueda y reemplazo. Si su editor de texto no incluye un analizador de C++ (y la mayoría no), los nombres de una sola letra provocarán una gran cantidad de coincidencias espurias que no pretendía. Con nombres más largos/descriptivos, OTOH, es más probable que la función de búsqueda y reemplazo funcione según lo previsto.

1

Si es solo un tipo, tiendo a usar identificadores de una sola letra (T, U, etc.). Si el argumento tiene un significado especial más limitado (predicado, asignador, etc.), usaría algo más descriptivo.

Sin embargo, los identificadores de una sola letra (T) pueden retroceder, colisionando con los nombres de las macros (ver GCC 4.2 Template strange error), que probablemente sea más improbable con los identificadores más largos (si no usan la misma convención ALL_CAPS como macros) .

Cuestiones relacionadas