2012-01-05 13 views
7

Más o menos lo que sugiere el título. Mientras estoy en not yet using C++0x me gustaría estar preparado para cuando suceda, y también me gustaría reducir la cantidad de código que tengo que reescribir para usar algunas de sus instalaciones. De esa forma puedo avanzar y retroceder la compatibilidad de una vez."Backporting" nullptr a C++ - programas pre-C++ 0x

Una de las más interesantes que he encontrado es nullptr, que he estado usando más a menudo recientemente.

Después de comprobar la "Solución oficial" y Meyer's suggestion, decidí que me gustaría utilizar esto en mis programas C++ y C++ 0x futuros. La segunda parte es simple: al ser una palabra clave, solo se admitirá el nullptr. Pero la primera parte me está causando cierta incomodidad.

El Meyers funciones propuesta como esta:

class nullptr_t { // ← this is my issue 
    // definition of nullptr_t 
} nullptr = { }; 

El problema con esta propuesta es que se declara el tipo de ser declarada como std::nullptr_t como es requerido por C++ 0x. Lo que significa que la solución para "sentirse nativo" tiene que hacerse volviendo a abrir el espacio de nombres std:: para agregar un tipo. Tengo el entendimiento de que es ilegal hacer en un programa de C++ (a diferencia de agregar especializaciones que aparentemente parece fruncir-y-dejar-ir-con-una-advertencia).

Quiero usar nullptr en una cómoda forma Y legal en un programa en C++. Una de las opciones que había pensado en declarar fue el tipo en otro espacio de nombres y luego llevarlo en el uso de using:

namespace mylibrary { 
class nullptr_t { 
    .... 
} nullptr = { }; 
// end namespace 
} 

// These would have to go in the header file. 
using mylibrary::nullptr; 
using mylibrary::nullptr_t; // apparently this is necessary as well? 

sería este el camino correcto para hacer que funcione? Obligaría a las directivas using, lo que también obliga a un orden específico de directivas #include. ¿Tendría razón al esperar que ningún código pre-C++ 0x solicite el tipo nullptr_t con espacio de nombres (como un tipo de argumento de función, por ejemplo)? ¿Funcionaría realmente "sentirse nativo" si se hace de esta manera?


Como una adición, es una bienvenida o mal visto que hay que tratar de acondicionarlo alguna ingeniosa C++ 0x cosas a C++ para una mejor compatibilidad y la codificación? Mientras tanto, he integrado esta solución y otras en las que estoy trabajando en in a piece of software to be released.

Respuesta

0

La razón principal por la que no se le permite añadir cosas a namespace std no es por lo que desordenar las cosas que ya están allí. Esto de otra manera podría hacerse fácilmente. Algo que encontré en el pasado fueron definiciones múltiples para operadores de salida para contenedores instanciados con un tipo incorporado como std::vector<int>. Sin embargo, nullptr_t no está definido en este espacio de nombres y agregar un typedef debería ser bastante inofensivo. Es decir, definiría nullptr_t en un espacio de nombre diferente que namespace std y luego agregaría un typedef para nullptr_t a namespace std. La variable nullptr debe declararse en el ámbito global de todos modos, ya que se utiliza sin reservas en C++ 2011.

Si se necesita el tipo std::nullptr_t depende de si le interesa agregar las firmas con este tipo. Por ejemplo, std::shared_ptr<T> se puede comparar con nullptr. Para esto, es necesario agregar sobrecargas adecuadas que mencionen el tipo std::nullptr_t (o utilizar algún otro nombre para este tipo).

+0

Siempre pensé que la razón por la que no puedes agregar cosas a 'namespace std' no es para no estropear las cosas que están ahí, sino para que tu código se compile en muchos compiladores (que podrían estar usando el nombre eligió), por lo que continúa compilando cuando el estándar agrega cosas al espacio de nombres 'std'. –

+0

(1) Creo que el espacio de nombres está reservado _para la implementación_ por lo que '' tiene permitido hacer lo que quiera en 'std'. (2) Esto es para que si mi código _only_ compila con una biblioteca estándar, puede compilar con _todas otras implementaciones compatibles_ de la biblioteca estándar. (3) Todos los nombres que terminan en '_t' están reservados para la implementación en C++ 03. –

+0

Por lo que entiendo, la regla "guión bajo" existe precisamente para que las "implementaciones" usen esos nombres libremente (solo examine cualquier copia de '', más allá de los nombres proporcionados por el Estándar (como 'cin',' cout') ningún otro nombre está reservado incluso en el espacio de nombres std; en ese punto, un 'typedef' no puede dañar la compatibilidad de avance que una declaración real puede, excepto que nos impide agregar _mucho_ cosas (como" espacios de nombres de detalles "). –

2

menos que se puede pensar en una razón tiene que declarar otra objeto de tipo nullptr_t (no puedo), me escondía el tipo de distancia y poner nullptr en el espacio de nombres global para imitar una palabra clave lo más cerca posible :

namespace mylibrary 
{ 
    class nullptr_t 
    { 
     .... 
    }; 
} 

mylibrary::nullptr_t nullptr = { }; 
+1

Sí, ocultar el tipo de distancia es lo que quiero hacer. Estoy más o menos preocupado si hay alguna razón por la que alguien necesite usar el * tipo * 'nullptr_t' para cualquier cosa que no se pueda hacer simplemente pasando' nullptr' o un tipo de puntero. –