¿Qué cambios introducidos en C++14 pueden potencialmente romper un programa escrito en C++11?


Introducción

Con el C++14 (aka. C++1y) Estándar en un estado cercano a ser final, los programadores deben preguntarse acerca de la compatibilidad hacia atrás, y los problemas relacionados con tal.


La cuestión

En las respuestas de a esta pregunta se afirma que el Estándar tiene un Apéndice dedicado a la información sobre los cambios entre revisiones.

Sería útil si estos problemas potenciales en el antes mencionado Apéndice podría ser explicado, tal vez con la ayuda de cualquier documento formal relacionado con lo que allí se menciona.

  • De acuerdo con el Estándar: ¿Qué cambios introducidos en C++14 pueden potencialmente romper un programa escrito en C++11?
Author: Community, 2014-06-01

1 answers

Nota: En este post considero que un "breaking change " es uno, o ambos, de;
1. a change that will make legal C++11 ill-formed when compiled as C++14, and;
2. un cambio que cambiará el comportamiento del tiempo de ejecución cuando se compila como C++14, vs C++11.


C++11vs C++14, ¿qué dice el Estándar?

El borrador estándar (n3797 ) tiene una sección dedicada a este tipo de información, donde describe la diferencias (potencialmente rompedoras) entre una revisión del estándar y otra.

Este post ha utilizado esa sección, [diff.cpp11], como base para una discusión semi-elaborada sobre los cambios que podrían afectar el código escrito para C++11, pero compilado como C++14.


C. 3. 1] Separadores de dígitos

El separador de dígitos se introdujo para que uno pudiera, de una manera más legible, escribir literales numéricos y dividirlos de una manera que sea más forma natural.

int x = 10000000;   // (1)
int y = 10'000'000; // (2), C++14

Es fácil verlo.(2) es mucho más fácil de leer que (1) en el fragmento anterior, mientras que ambos inicializadores tienen el mismo valor.

El problema potencial con respecto a esta característica es que la comilla simple siempre denotó el inicio/final de un carácter-literal en C++11, pero en C++14 a comilla simple puede estar rodeando a un carácter-literal, o utilizado en el manera mostrada previamente(2).


Fragmento de ejemplo, legal en C++11y C++14, pero con un comportamiento diferente.

#define M(x, ...) __VA_ARGS__

int a[] = { M(1'2, 3'4, 5) };

// int a[] = { 5 };        <-- C++11
// int a[] = { 3'4, 5 };   <-- C++14
//                              ^-- semantically equivalent to `{ 34, 5 }`

(Nota: Se puede encontrar más información sobre comillas simples como separadores de dígitos en n3781.pdf )


C. 3. 2] Desasignación de tamaño

C++14 presenta la oportunidad de declarar una sobrecarga global de operator delete adecuada para de tamaño desasignación, algo que no era posible en C++11.

Sin embargo, el Estándar también exige que un desarrollador no puede declarar solo una de las dos funciones relacionadas a continuación, debe declarar ya sea ninguna, o ambas; que se indica en [nuevo.eliminar.single] p11 .

void operator delete (void*) noexcept;
void operator delete (void*, std::size_t) noexcept; // sized deallocation


Más información sobre el problema potencial:

Programas existentes que redefinen el tamaño global versión no también definir la versión de tamaño. Cuando una implementación introduce un tamaño versión, el reemplazo estaría incompleto y es probable que programs would call the implementation-provided sized deallocator on objetos asignados con el asignador proporcionado por el programador.

Nota : Cita tomada de Desasignación de tamaño n3536-C++

(Nota: Más de interés está disponible en el artículo titulado n3536-Desasignación de tamaño C++ , escrito por Lawrence Crowl )


C. 3. 3] constexpr funciones miembro, ya no implícitas const

Hay muchos cambios a constexpr en C++14, pero el único cambio que va a cambiar la semántica entre C++11, y C++14 es constantness de a miembro de la función marcado como constexpr.

La razón detrás de este cambio es permitir constexpr miembro de funciones para mutar el objeto al que pertenecen, algo que es posible debido a la relajación de constexpr.

struct A { constexpr int func (); };

// struct A { constexpr int func () const; }; <-- C++11
// struct A { constexpr int func ();       }; <-- C++14


Material recomendado sobre este cambio, y por qué es lo suficientemente importante para introducir una posible rotura de código:


Fragmento de ejemplo, legal en C++11 y C++14 , pero con un comportamiento diferente

struct Obj {
  constexpr int func (int) {
    return 1;
  }

  constexpr int func (float) const {
    return 2;
  }
};

Obj const a = {}; 
int const x = a.func (123);

// int const x = 1;   <-- C++11
// int const x = 2;   <-- C++14

C. 3. 4] Eliminación de std::gets

std::gets ha sido eliminado de la Biblioteca Estándar porque es considerado peligroso.

Las implicaciones de esto es, por supuesto, que tratar de compilar código escrito para C++11, en C++14, donde se utiliza una función de este tipo probablemente fallará en compilar.


(Nota: hay formas de escribir código que no falla en compilar, y tienen un comportamiento diferente, que depende de la eliminación de std::gets de la Biblioteca Estándar )

 228
Author: Filip Roséen - refp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-15 16:56:28