2009-04-17 10 views
12

1) ¿Cuál es la convención utilizada en la práctica cuando typedef'ing¿Cuál es la convención de nomenclatura cuando los mapas STL complejos typdef?

algo así como

typedef std::map<SomeClass*, SomeOtherClass> [SomeStandardName>] 
typedef std::map<SomeClass*, std<SomeOtherClass> > <[SomeStandardName] 

2) ¿Dónde sueles poner typedef: archivos de cabecera a nivel global y local a la clase?

3) ¿Escribe usted iteradores o const map <> versión?

4) Supongamos que tiene un mapa que utilizan dos conceptos diferentes, ¿crea dos typedefs separados?

typedef map<string, SomeClass *> IDToSomeClassMap; 
typedef map<string, SomeClass *> DescriptionToSomeClassMap; 

Gracias


Edición # 1

Estoy interesado específicamente en typedef mapas STL, como

typedef map<int, string> IdToDescriptionMap 

o

typedef map<int, string> IdToDescription 

¿Cuáles son las prácticas más comunes?

Respuesta

12

prefiero la siguiente convención:

typedef std::map< Foo, Bar > FooToBarMap 

deliberadamente evito typedef'ing los iteradores, prefiero hacer referencia explícita a ellos como:

FooToBarMap::const_iterator 

Desde los iteradores son ya un de facto nombre de tipo estándar. Y FooToBarMapConstIter es menos claro de leer cuando se escanea el código, me parece.

0

No sé si hay reglas formales sobre el tema, pero generalmente agrego las defs de tipo en el lugar que mejor se ajuste al uso dentro del proyecto.

  • Si el typedef sólo se utiliza dentro de una clase a continuación, añadir el typedef dentro de la definición de clase
  • Si el typedef es utilizado por varias clases no relacionadas añadirlo en un archivo de cabecera a un nivel de ámbito espacio de nombres

En cuanto al nombre real del tipo typedef'd. Lo nombro lo que tenga sentido para typedef. No le doy a los nombres typedef ninguna convención especial como el prefijo con _t o cualquier cosa en esa línea. Por ejemplo

typedef stl::map<stl::string,Student> NameToStudentMap; 
0

Ninguno, sólo tener en cuenta las normas generales para nombrar identificadores (sin _ para empezar etc.). Además, si su organización tiene una guía de codificación, lo mejor es mantenerla.

A menudo, al definir su propia clase de plantilla, se vuelve desordenada sin typedefs, así que los crearía allí como atajos útiles. Sin embargo, si realmente es un grupo de clases, preferiría tenerlo en el nivel namespace.

+0

Estoy interesado específicamente en los mapas STL typedef, como typedef mapa IdToDescriptionMap o typedef mapa IdToDescription Cuál es la práctica común? –

+0

Mencioné lo que hacemos en general, no hay reglas especiales para los mapas. FWIW, podemos llamar a un mapa a Dict si conviene al entorno del objeto. – dirkgently

+0

+1 ........... ganado !!! –

0

se utiliza la siguiente en mi puesto de trabajo:

 
typedef std::map WhateverMap; 
typedef WhateverMap::iterator WhateverIter; 
typedef WhateverMap::const_iterator WhateverCIter; 

En cuanto a la ubicación, que varía. Si es específico de una clase, puede estar en una estructura Impl, o puede estar en las áreas protegidas o privadas de la declaración de clase. Si es más general (se usa en todos los archivos, se usa en una API), lo colocamos en un encabezado de estilo "FooTypes.h" por separado.

Tenga en cuenta que dado que a veces es frecuente que cambiemos el tipo subyacente, podemos usar "WhateverCollection" en lugar de "WhateverVec" o "WhateverList".No es infrecuente que una "ListaLista" realmente se defina con un vector o una barra deslizante, dependiendo de la huella deseada y las características de rendimiento.

2

No existe una regla generalmente aceptada sobre estos nombres. Lo que suelo hacer es usar el nombre de la clase "valor" con el sufijo Map. En su ejemplo, sería SomeOtherClassMap. Yo uso esta convención porque generalmente es más interesante que tu mapa contenga objetos de "valor" del tipo SomeOtherClass luego que los busques con "claves" de SomeClass.

0

cuestión de interés:
Miré en alza, y veo que no tienen ninguna norma global, pero la convención más utilizada

typedef std::map< key, value > some_domain_specific_name_map; 

o

typedef std::map< key, value > some_domain_specific_name_map_type; 

también una buena práctica para hacer typedef para value_type o iterators, generalmente tienen el mismo nombre que map pero con ending _value_type, _iterator.

0

Normalmente defino nombre relacionado al typedef que indica el tipo del objeto.

Ex:

typedef std::vector<ClassCompStudent*> StudentCollection; 

typedef std::map<std::string /*id*/, ClassCompStudent* /*pStudent*/> IDToStudentMap; 

También, los definen como público en la cabecera de la clase en la que se ha creado el objeto. Eso me da la ventaja de cambiar el tipo de contenedor sin romper el código del cliente.

class Test 
{ 
public: 
    typedef std::vector<ClassCompStudent*> StudentCollection; 

    /* Users of Test need not know whether I use vector or list for 
     storing students. They get student collection and use it*/ 
    bool getStudents(StudentCollection& studentList) const; 

    void print() 
    { 
     //do printing 
    } 
private: 

    StudentCollection m_StudentList; 
}; 

bool function(const Test& testObj) 
{ 
    //If StudentCollection gets changed to list, this code need not be changed. 
    StudentCollection aCollection; 
    testObj.getStudents(aCollection); 
    std::for_each(aCollection.begin(), aCollection.end(), std::mem_fun(&Test::print)); 
} 
0

Usando la palabra "Mapa" o "Vector" en el tipo de notación inútil. Estas son palabras relacionadas con la realización y no con el modelo de negocio.

No tiene que mostrar que este tipo es vectorial o de mapa. Puedes usar List. Como

typedef std::vector<std::string> List; 
typedef std::set<std::string> List; 

Estas dos son listas de cadenas. Y esto es verdad

typedef std::map<std::string, Object> List; 
or 
typedef std::map<std::string, Object> NamedList; 

Mi punto es que no utilice el tipo de notación húngara.

1

La segunda parte de la pregunta es la más interesante para mí. Prefiero poner typedef s dentro de las clases que los utilizan, cuando hay un lugar lógico para ellos, incluso si se usan en otras clases. Pero eso causa algunos problemas con las declaraciones hacia adelante (que utilizamos mucho para la velocidad de compilación).

Por ejemplo, en un proyecto reciente, tuvimos una clase llamada Io, con un typedef incorporada denominada Point, lo que hizo para el código muy legible - un Io::Point es muy clara y legible. Pero cada vez que queríamos usar el tipo, teníamos que incluir la declaración de la clase Io, incluso si todo lo que necesitábamos era la declaración de Io::Point, ya que no hay manera (que yo sepa) de reenviar-declarar un tipo que está dentro de un clase declarada adelante.

En ese caso, terminamos haciéndolo de ambas formas. Creamos un tipo global IoPoint, y luego typedef d Io::Point (de modo que nuestro código ya escrito no tuvo que ser modificado). No es la respuesta más bonita, pero hizo el trabajo.

En cuanto a las otras partes:

No utilizamos ningún convenio especial para los nombres. Para los mapas, a menudo utilizamos * DescriptiveSomething *** Map ** (ya que es poco probable que alguna vez cambiemos de un mapa a otro tipo de contenedor), pero si DescriptiveSomething es lo suficientemente descriptivo y no entra en conflicto con un existente nombre, a menudo lo usaremos en su lugar.

En general, no nos molestamos en crear typedefs para los iteradores, ya que es fácil (y muy legible) simplemente usar Type::iterator o Type::const_iterator. Dicho esto, nosotros do a veces typedef ellos si el nombre del tipo es tan largo que Type::const_iterator hace que el código se vea demasiado "grueso". (No sé de ninguna mejor manera de decirlo, pero probablemente sepa a qué me refiero.)

Creamos diferentes tiposdefis para cada concepto, incluso si dos de ellos definen exactamente el mismo tipo. Pueden cambiar independientemente el uno del otro, por lo que tener diferentes nombres de tipo para ellos simplifica cualquier refactorización posterior. También hace que el código sea más legible, en muchos casos.

Cuestiones relacionadas