c++ - ¿Puede el código de C ++ ser válido tanto en C ++ 03 como en C ++ 11 pero hacer cosas diferentes?



3 Answers

Le señalo gustedt.wordpress.com/2013/12/15/… y el seguimiento , que tiene un buen ejemplo de cómo >> puede cambiar el significado de C ++ 03 a C ++ 11 mientras compila ambos.

bool const one = true;
int const two = 2;
int const three = 3;

template<int> struct fun {
    typedef int two;
};

template<class T> struct fon {
    static int const three = ::three;
    static bool const one = ::one;
};

int main(void) {
    fon< fun< 1 >>::three >::two >::one; // valid for both  
}

La parte clave es la línea en main , que es una expresión.

En C ++ 03:

1 >> ::three = 0
=> fon< fun< 0 >::two >::one;

fun< 0 >::two = int
=> fon< int >::one

fon< int >::one = true
=> true

En C ++ 11

fun< 1 > is a type argument to fon
fon< fun<1> >::three = 3
=> 3 > ::two > ::one

::two is 2 and ::one is 1
=> 3 > 2 > 1
=> (3 > 2) > 1
=> true > 1
=> 1 > 1
=> false

Felicitaciones, dos resultados diferentes para la misma expresión. Por supuesto, el C ++ 03 apareció con una forma de advertencia Clang cuando lo probé.

c++ c++11 language-lawyer c++03

¿Es posible que el código C ++ se ajuste tanto al estándar C++03 estándar C++11 , pero hacen diferentes cosas dependiendo de bajo qué estándar se está compilando?




Un cambio potencialmente peligroso, incompatible con versiones anteriores, es en los constructores de contenedores de secuencia como std::vector , específicamente en la sobrecarga que especifica el tamaño inicial. Donde en C ++ 03, copiaron un elemento construido por defecto, en C ++ 11 construyeron por defecto cada uno.

Considere este ejemplo (usando boost::shared_ptr para que sea válido C ++ 03):

#include <deque>
#include <iostream>

#include "boost/shared_ptr.hpp"


struct Widget
{
  boost::shared_ptr<int> p;

  Widget() : p(new int(42)) {}
};


int main()
{
  std::deque<Widget> d(10);
  for (size_t i = 0; i < d.size(); ++i)
    std::cout << "d[" << i << "] : " << d[i].p.use_count() << '\n';
}

C ++ 03 ejemplo en vivo

C ++ 11 ejemplo en vivo

La razón es que C ++ 03 especificó una sobrecarga para "especificar tamaño y elemento de prototipo" y "especificar solo tamaño", como este (los argumentos del asignador se omiten por brevedad):

container(size_type size, const value_type &prototype = value_type());

Esto siempre copiará prototype en los tiempos de size contenedor. Cuando se le llama con un solo argumento, por lo tanto, creará copias de size de un elemento construido por defecto.

En C ++ 11, esta firma del constructor se eliminó y se reemplazó con estas dos sobrecargas:

container(size_type size);

container(size_type size, const value_type &prototype);

El segundo funciona como antes, creando copias de size del elemento prototype . Sin embargo, el primero (que ahora maneja las llamadas con solo el argumento de tamaño especificado) construye cada elemento de manera individual.

Supongo que la razón de este cambio es que la sobrecarga de C ++ 03 no sería utilizable con un tipo de elemento de solo movimiento. Pero no obstante, es un cambio importante, y rara vez se documenta en eso.




Este hilo Qué diferencias, si las hay, entre C ++ 03 y C ++ 0x pueden detectarse en tiempo de ejecución tiene ejemplos (copiados de ese hilo) para determinar las diferencias de idioma, por ejemplo, aprovechando el colapso de referencia de C ++ 11:

template <class T> bool f(T&) {return true; } 
template <class T> bool f(...){return false;} 

bool isCpp11() 
{
    int v = 1;
    return f<int&>(v); 
}

y c ++ 11 permitiendo tipos locales como parámetros de plantilla:

template <class T> bool cpp11(T)  {return true;} //T cannot be a local type in C++03
                   bool cpp11(...){return false;}

bool isCpp0x() 
{
   struct local {} var; //variable with local type
   return cpp11(var);
}



Related