He estado trabajando durante un buen tiempo para mantener un nivel de compatibilidad hacia adelante y hacia atrás en mis programas C ++, hasta que finalmente tuve que hacer un kit de herramientas de la biblioteca , que estoy preparando para el lanzamiento ya se ha lanzado. En general, siempre que acepte que no obtendrá una compatibilidad hacia adelante "perfecta" ni en las características (algunas cosas simplemente no se pueden emular hacia adelante) no en la sintaxis (probablemente tendrá que usar macros, espacios de nombres alternativos para algunas cosas) entonces ya está todo listo.
Hay una gran cantidad de características que se pueden emular en C ++ 03 en un nivel que es suficiente para un uso práctico, y sin todas las molestias que conlleva, por ejemplo: Boost. Diablos, incluso la propuesta de estándares de C ++ nullptr
sugiere un backport C ++ 03. Y luego está TR1, por ejemplo, para todo lo relacionado con C ++ 11, pero hemos tenido previsualizaciones durante años. ¡No solo eso, algunas características de C ++ 14 como variantes de aserción, functores transparentes y optional
se pueden implementar en C ++ 03!
Las dos únicas cosas que sé que no se pueden respaldar son las plantillas constexpr y variadic.
Con respecto a todo el asunto de agregar cosas al espacio de nombres std
, mi opinión es que no importa , en absoluto. Piense en Boost, una de las bibliotecas de C ++ más importantes y relevantes, y su implementación de TR1: Boost.Tr1. Si desea mejorar C ++, hágalo compatible con C ++ 11, luego, por definición, lo está convirtiendo en algo que no es C ++ 03, por lo que bloquearse a sí mismo en un Estándar que tiene la intención de evitar o dejar atrás de todos modos es En pocas palabras, contraproducente. Los puristas se quejarán, pero por definición uno no debe preocuparse por ellos.
Por supuesto, solo porque no seguirás el Estándar (03) después de todo no significa que no puedas intentarlo, o que irás alegremente rompiéndolo. Ese no es el punto. Siempre y cuando mantenga un control muy cuidadoso de lo que se agrega al std
espacio de nombres y controle los entornos en los que se utiliza su software (es decir, ¡haga las pruebas!), No debería haber ningún daño irremediable. Si es posible, defina todo en un espacio de nombres separado y solo agregue using
directivas al espacio de nombres std
para que no agregue nada más allá de lo que "absolutamente" debe incluir. Lo cual, IINM, es más o menos lo que hace Boost.TR1.
Actualización (2013) : como solicitud de la pregunta original y viendo algunos de los comentarios que no puedo agregar debido a la falta de representación, aquí hay una lista de características de C ++ 11 y C ++ 14 y su grado de portabilidad a C ++ 03:
nullptr
: completamente implementable dado el respaldo oficial del Comité; probablemente también tendrá que proporcionar algunas especializaciones de type_traits para que se reconozca como un tipo "nativo".
forward_list
: completamente implementable, aunque el soporte del asignador se basa en lo que puede proporcionar su implicación Tr1.
- Nuevos algoritmos (partición_copias, etc.): totalmente implementables.
- Construcciones de contenedores a partir de secuencias de llaves (p. Ej . :)
vector<int> v = {1, 2, 3, 4};
: completamente implementable, aunque más extenso de lo que uno quisiera.
static_assert
: casi completamente implementable cuando se implementa como una macro (solo tendrá que tener cuidado con las comas).
unique_ptr
: casi completamente implementable, pero también necesitará soporte del código de llamada (para almacenarlos en contenedores, etc.); Ver el siguiente sin embargo.
- rvalue-references: casi completamente implementable dependiendo de cuánto espere obtener de ellos (por ejemplo: Boost Move).
- Para cada iteración: casi completamente implementable, la sintaxis será algo diferente.
- usando funciones locales como argumentos (por ejemplo: transformación): casi completamente implementable, pero la sintaxis diferirá lo suficiente; por ejemplo, las funciones locales no están definidas en el sitio de la llamada, sino justo antes.
- operadores de conversión explícitos: implementables a niveles prácticos (haciendo que la conversión se haga explícita), ver "cast_cast "de Imperfect C ++ ; pero la integración con características del lenguaje como
static_cast<>
podría ser casi imposible.
- reenvío de argumentos: implementable a niveles prácticos dado lo anterior en rvalue-references, pero necesitará proporcionar N sobrecargas a sus funciones tomando argumentos reenviables.
- mover: implementable a niveles prácticos (ver los dos anteriores). Por supuesto, tendría que usar contenedores modificadores y objetos para beneficiarse de esto.
- Asignadores de ámbito: no es realmente implementable a menos que su implementación Tr1 pueda ayudarlo.
- Tipos de caracteres multibyte: No es realmente implementable a menos que su Tr1 pueda soportarlo. Pero para el propósito previsto, es mejor confiar en una biblioteca específicamente diseñada para tratar el asunto, como la UCI, incluso si usa C ++ 11.
- Listas de argumentos variables: implementable con algunos problemas, preste atención al reenvío de argumentos.
noexcept
: depende de las características de su compilador.
- Nuevos
auto
semántica y decltype
: depende de las características del compilador - por ejemplo .: __typeof__
.
- tipos enteros de tamaño (
int16_t
, etc.): depende de las características de su compilador, o puede delegar en el stdint.h portátil.
- atributos de tipo: depende de las características de su compilador.
- Lista de inicializadores: no se puede implementar, que yo sepa; sin embargo, si lo que desea es inicializar contenedores con secuencias, consulte lo anterior sobre "construcciones de contenedores".
- Alias de plantillas: no es implementable, que yo sepa, pero es una característica innecesaria de todos modos, y hemos tenido
::type
en plantillas para siempre
- Plantillas variadas: no se puede implementar a mi entender; el cierre es el argumento de plantilla predeterminado, que requiere N especializaciones, etc.
constexpr
: No se puede implementar a mi entender.
- Inicialización uniforme: no es implementable, que yo sepa, pero la inicialización de constructor predeterminada garantizada se puede implementar con el valor inicializado de Boost.
- C ++ 14
dynarray
: totalmente implementable.
- C ++ 14
optional<>
: casi completamente implementable siempre que su compilador C ++ 03 admita configuraciones de alineación.
- Funcionarios transparentes C ++ 14: casi completamente implementables, pero su código de cliente probablemente tendrá que usar explícitamente, por ejemplo:
std::less<void>
para que funcione.
- C ++ 14 nuevas variantes de aserción (como
assure
): completamente implementable si desea afirmaciones, casi completamente implementable si desea habilitar tiros en su lugar.
- Extensiones de tupla de C ++ 14 (obtenga el elemento de tupla por tipo): totalmente implementable, e incluso puede hacer que no se compile con los casos exactos descritos en la propuesta de características.
(Descargo de responsabilidad: varias de estas características se implementan en mi biblioteca de backports C ++ que he vinculado anteriormente, por lo que creo que sé de lo que estoy hablando cuando digo "completamente" o "casi completamente").