2011-08-05 5 views
16

En este article on defining your own extensions to ::std::error_code El autor recomienda este código:¿Está bien inyectar una especialización en el espacio de nombres estándar?

namespace std 
{ 
    template <> 
    struct is_error_code_enum<http_error> 
    : public true_type {}; 
} 

con el fin de permitir a las conversiones de sus propias constantes de error en el tipo de error del sistema.

¿Es esto razonable? Siempre me pone nervioso poner cosas en el espacio de nombre std. ¿Hay una mejor manera de lograr el objetivo? En su defecto, ¿hay alguna parte del estándar que diga que esto siempre está bien?

Respuesta

23

Sí, especializaciones (para los tipos definidos por el usuario) de los tipos de ETS existentes son lo solamente se le permite poner en el espacio de nombres std, siempre y cuando la especialización cumple los requisitos de la plantilla original.

Véase 17.6.4.2.1 en el borrador de C++ 0x.

Nuevos tipos, sobrecargas de funciones y cualquier otra cosa, por supuesto, está prohibido. Pero se permite la especialización de plantillas existentes.

+1

Tiene la mejor respuesta, pero @ Steve314 incluye el detalle importante de que en algunos casos es absolutamente necesario hacer esto. Probablemente esperaré unas horas (solo en principios generales) y probablemente acepte esta. – Omnifarious

8

Esto no solo es correcto, es esencial en algunos casos. Lo que no debe hacer es definir funciones/clases/plantillas completamente nuevas dentro de std.

std::swap en particular es una cosa común y simple para especializarse. Algunas clases deben hacer esto para permitir intercambios eficientes, básicamente intercambiando referencias privadas para intercambiar internos en lugar de usar la implementación temporal y asignaciones predeterminada.

EDITAR

El comentario de Ildjarn menciones ADL - Argument Dependent name Lookup. La página de Wikipedia menciona específicamente std::swap en la sección "Interfaces" y "Crítica".

La sección 13.5.2 de Stroustrup (Edición especial) incluye un ejemplo de especialización de std::swap. Citando de que ...

Estas especializaciones de less() y swap() se utilizan en la biblioteca estándar (16.3.9, 20.3.16). Además, son ejemplos de técnicas ampliamente aplicables.

Siempre he leído que como una indicación de que la especialización de std::swap era lo correcto a hacer, y nunca he lo suficientemente preocupado por ADL a la pregunta de que, pero es posible que hay una brecha entre "utilizado en la norma biblioteca "y" técnicas ampliamente aplicables "- que esta técnica no se debe usar para especializar std::swap para manejar tipos que no están en std.

También es posible que haya un problema de estilo que no se haya resuelto cuando se publicó la edición especial. AFAIK, Stroustrup ha agregado algunos apéndices adicionales y ha aplicado algunas erratas, pero de lo contrario no ha revisado sustancialmente el contenido.

Según la página de Wikipedia, hay es un problema potencial con la mezcla de la adición de especializaciones y ADL - a veces puede obtener ambigüedad impidiendo cualquier búsqueda.Esto solo ocurre si mezclas las dos técnicas, y ADL es conocido por llevar a problemas semánticos de todos modos. Pero ese argumento solo lleva a "no usar ADL en absoluto", pero ADL existe por alguna razón.

Bueno, sí, ADL existe por una razón: para que las funciones y operadores que no son miembros y que trabajan con un tiempo sean visibles junto con el tipo. Pero std::swap no está asociado con un tipo particular: es genérico, y solo las especializaciones particulares están asociadas a tipos particulares. Si quiere que std::swap esté visible, quiere el espacio de nombre std. ADL no es necesario para que funcione y, como señala la página de Wikipedia, hay críticas a ADL.

Lo que esto significa es, básicamente, que no sé. Tengo mis racionalizaciones. No necesariamente están de acuerdo con reglas de estilo más generalizadas. Ciertamente, este comentario demuestra que no es esencial para especializarse std::swap - puede suministrar su propio swap y confiar en ADL en su lugar. Tal vez sea preferido.

Probablemente regrese y vuelva a editar después de haber comprobado.

+2

'std :: swap' should ** not ** debe estar especializado o sobrecargado; en su lugar, debe poner una función' swap' libre en el mismo espacio de nombres que el tipo que se intercambia, y dejar que ADL haga el resto. – ildjarn

+0

@ildjarn - gracias - No estoy seguro de que tengas razón todavía, pero mira la edición. – Steve314

+0

ADL se rompió ampliamente en los principales compiladores durante bastante tiempo, por lo que la especialización 'std :: swap' se convirtió en una práctica estándar. Sin embargo, con compiladores modernos que cumplen con los estándares, esa solución ya no es necesaria. – ildjarn

Cuestiones relacionadas