2011-04-16 12 views
6

que estaba buscando a través de la Google C++ style guide, y me encontré con esto:.¿Mala práctica para declarar nombres en el espacio de nombres estándar?

"no se declara nada en namespace std, ni siquiera hacia adelante declaraciones de clases de la biblioteca estándar Declarar entidades en namespace std es un comportamiento indefinido, es decir, no es portátil. Para declarar entidades de la biblioteca estándar, incluya el archivo de encabezado apropiado ".

¿Podría alguien explicar lo que esto significa y por qué esto es un comportamiento indefinido usando un código de ejemplo?

Respuesta

11

¿Podría alguien explicar lo que esto significa y por qué esto es un comportamiento indefinido usando un código de ejemplo?

los siguientes rendimientos del programa comportamiento indefinido:

namespace std { 
    void foo(int) { } 
} 

#include <iostream> 

int main() { 
    std::cout << "Hello World!" << std::endl; 
} 

¿Por qué? Declara una función llamada foo en el espacio de nombres std. En cuanto a por qué esto podría causar un problema, considere: la implementación de la Biblioteca estándar podría tener su propia función llamada foo() y que podría ser utilizada por algún componente en <iostream>. Su foo podría ser una mejor coincidencia que la implementación de la Biblioteca estándar foo.

+1

Excepto que especializa 'std :: swap <>()'. Estamos autorizados a hacer eso. : p – wilhelmtell

+0

@wilhelmtell: incluso esa es una forma muy pobre. Es mejor definir una sobrecarga de intercambio en el mismo espacio de nombres que su tipo y dejar que ADL haga el trabajo de encontrarlo. – ildjarn

+4

@wilhelmtell: Puede _especializar_ plantillas 'std'; no puede _overload_ plantillas 'std'. Para 'swap', la solución preferida, como dice @ildjarn, es usar una función de ámbito de espacio de nombres que se puede encontrar a través de ADL. C++ 0x otorga aprobación formal a esa técnica mediante la adición de un concepto "Swappable". –

6

Esto significa no declarar sus propios tipos en el espacio de nombre std. Puede usar la biblioteca estándar, pero debe hacerlo incluyendo el encabezado apropiado.

Básicamente, asegúrese de que todas sus declaraciones estén en su propio espacio de nombres, no en std.

4

Están diciendo que usted no debe hacia adelante cosas declarar de la biblioteca estándar de la siguiente manera:

// myheader.h 
namespace std{ 
template<class T> 
void SomeStandardFunction(); 
} 

// use std::SomeStandardFunction 

En cambio, sólo debe incluir la cabecera directamente:

// myheader.h 
#include <SomeHeaderThatContainsSomeStandardFunction> 

// use std::SomeStandardFunction 
+0

Falta espacio en blanco: plantilla > vector; (-: – snoofkin

+0

@soul: Un problema más evidente fue la falta de ';' después de 'allocator', y ese' allocator' necesita definirse completamente antes de ser utilizado como un parámetro de plantilla, así que cambié el ejemplo. :) – Xeo

2

Esto no significa "No utilice la biblioteca estándar".

Usar algo y declarar algo son dos cosas diferentes. Está diciendo que no declares nada, ya que no haces algo como "clase ostream". Supongo que la gente solía tener que declararlo así para poder usarlo, pero ahora, como las cosas se declaran en el espacio de nombres estándar, simplemente incluye el archivo de encabezado.

Verificar this salir.

10

En primer lugar, al igual que gran parte de la guía de estilo de Google, en realidad está mal. El estándar específicamente le permite definir algunas entidades específicas en el espacio de nombres std (por ejemplo, especializaciones de plantillas existentes sobre tipos definidos por el usuario).

Ignorando esas excepciones, sin embargo, tienen la idea general correcta: su código normalmente pertenece a algún lugar otro que el espacio de nombres estándar. Puede colocarlo en el espacio de nombre global, o puede definir otro espacio de nombre, pero debe dejar std solo.

También debe no tratar de visión de declarar nada en la biblioteca estándar. Las funciones estándar están permitidas (por ejemplo) para incluir parámetros adicionales, siempre que incluyan valores predeterminados, para que puedan invocarse de la manera estándar. Si intenta declararlos usted mismo, en lugar de declarar la función existente, podría terminar declarando una sobrecarga ambigua.

En pocas palabras: sí, utilice la biblioteca estándar. Cuando lo use, obtenga las declaraciones incluyendo los encabezados estándar, no intente escribir el suyo propio.

+1

+1 por darme la vuelta:" en realidad es incorrecto ... especializaciones de plantillas existentes ... ". Es una práctica común y aceptable especializar 'std :: swap <>()'. – wilhelmtell

+4

+1 por "En primer lugar, ** como gran parte de la guía de estilo de Google **, en realidad está mal". – ildjarn

Cuestiones relacionadas