228 votes

Quelles sont les modifications de rupture introduites dans C ++11?

Je sais qu'au moins l'un des changements dans C ++ 11 provoquera l'arrêt de la compilation d'un ancien code: l'introduction de explicit operator bool() dans la bibliothèque standard, en remplaçant les anciennes instances de operator void*() . Certes, le code que cela va casser est probablement du code qui n'aurait pas dû être valide en premier lieu, mais c'est quand même un changement de rupture: les programmes qui étaient valides ne le sont plus.

Y a-t-il d'autres changements de rupture?

178voto

Le FDIS a une section pour les incompatibilités, à l'annexe C.2 "C++ et ISO C++ 2003".

Résumé, en paraphrasant le FDIS ici, pour le faire (mieux) approprié comme une SORTE de réponse. J'ai ajouté quelques exemples de mon propre à illustrer les différences.

Il y a un peu de la bibliothèque liés à des incompatibilités où je ne sais pas exactement les implications de l', je laisse donc ceux pour les autres à développer.

Langage de base


#define u8 "abc"
const char *s = u8"def"; // Previously "abcdef", now "def"

#define _x "there"
"hello"_x // now a user-defined-string-literal. Previously, expanded _x .

Mots-clés: alignas, alignof, char16_t, char32_t, constexpr, decltype, noexcept, nullptr, static_assert, et thread_local


Certains les littéraux entiers plus grands que ce qui peut être représenté par temps pouvez modifier à partir d'un type entier non signé signé de longue de longue.


Valide en C++ 2003 code qui utilise la division entière arrondit le résultat vers 0 ou vers l'infini négatif, alors que C++0x toujours arrondit le résultat vers 0.

(certes, pas vraiment un problème de compatibilité pour la plupart des gens).


Valide en C++ 2003 code qui utilise le mot-clé auto comme une classe de stockage spécificateur peut être invalide en C++0x.


Rétrécissement des conversions provoquer des incompatibilités avec C++03. Par exemple, le code suivant est valide en C++ 2003, mais non valides dans la présente Norme Internationale parce que le double, int est un rétrécissement de conversion:

int x[] = { 2.0 };

Implicitement déclarées spécial des fonctions membres sont définis comme étant supprimés lors de la définition implicite aurait été mal formé.

Valide en C++ 2003 programme qui utilise l'une de ces fonctions de membre dans un contexte où la définition n'est pas nécessaire (par exemple, dans une expression qui n'est pas potentiellement évalué) devient mal formé.

Par exemple moi:

struct A { private: A(); };
struct B : A { };
int main() { sizeof B(); /* valid in C++03, invalid in C++0x */ }

Ces sizeof astuces ont été utilisés par certains SFINAE, et doit être changé maintenant :)


L'utilisateur déclaré destructeurs ont une exception implicite de la spécification.

Par exemple moi:

struct A {
  ~A() { throw "foo"; }
};

int main() { try { A a; } catch(...) { } }

Ce code appelle terminate dans C++0x, mais ne pas en C++03. Parce que l'exception implicite spécification d' A::~A dans C++0x est - noexcept(true).


Valide en C++ 2003 déclaration contenant export est mal formé dans C++0x.


Valide en C++ 2003 expression contenant > , suivi immédiatement par un autre > peuvent maintenant être traitées comme la fermeture de deux modèles.

En C++03, >> serait toujours la maj opérateur jeton.


Permettre dépendante des appels de fonctions avec une liaison interne.

Par exemple moi:

static void f(int) { }
void f(long) { }

template<typename T>
void g(T t) { f(t); }

int main() { g(0); }

En C++03, cela nécessite, f(long), mais en C++0x, cela nécessite, f(int). Il convient de noter que dans les deux C++03 et C++0x, à la suite d'appels f(B) (l'instanciation contexte encore ne considère que extern lien déclarations).

struct B { };
struct A : B { };

template<typename T>
void g(T t) { f(t); }

static void f(A) { }
void f(B) { }

int main() { A a; g(a); }

Meilleure correspondance f(A) n'est pas prise, parce qu'il n'a pas de liaison externe.


Modifications de bibliothèque

Valide en C++ 2003 code qui utilise tous les identificateurs ajouté à la norme C++ bibliothèque de C++0x peut ne pas compiler ou de produire des résultats différents dans la Présente Norme Internationale.


Valide en C++ 2003 code #includes - têtes avec de nouveaux noms de C++0x bibliothèque standard en-têtes peuvent être non valide dans la présente Norme Internationale.


Valide en C++ 2003 code qui a été compilé en attendant échange sera en <algorithm> peut-être à la place comprennent <utility>


L'espace de noms global posix est désormais réservé à la normalisation.


Valide en C++ 2003 code qui définit override, final, carries_dependencyou noreturn sous forme de macros n'est pas valide en C++0x.

28voto

arsenm Points 1834

La signification du mot-clé auto a été modifiée.

24voto

Downvoter Points 453

Briser le changement?

Eh bien, d'une part, si vous avez utilisé decltype , constexpr , nullptr , etc. comme identifiants, vous pourriez avoir des ennuis ...

22voto

Certains d'incompatibilités qui ne sont pas couverts par les incompatibilités de l'article:


C++0x traite le injecté nom de la classe comme un modèle, si le nom est passé en argument à un modèle de paramètre du modèle, et comme un type si il est passé à un modèle de type de paramètre.

Valide en C++03 code peut se comporter différemment si elle repose sur l'injection nom de la classe à être toujours un type dans ces scénarios. Exemple de code prises à partir de mon clang PR

template<template<typename> class X>
struct M { };

template<template<typename> class X>
void g(int = 0); // #1

template<typename T>
void g(long = 0); // #2

template<typename T>
struct A {
  void f() {
    g<A>(); /* is ambiguous in C++0x */
    g<A>(1); /* should choose #1 in C++0x */
  }
};

void h() {
  A<int> a;
  a.f();
}

En C++03, le code appelle la deuxième g deux fois.


C++0x fait quelques noms qui étaient à la charge en C++03 maintenant être non-dépendants. Et nécessite la recherche d'un nom pour les non-dépendants qualifié noms qui se réfèrent à des membres de l'actuel modèle de classe pour être répété à l'instanciation, et nécessite une vérification que ces noms de la recherche de la même manière que fait à la définition de modèle de contexte.

Valide en C++03 code qui dépend de la prédominance de la règle peut maintenant compile pas plus à cause de ce changement.

Exemple:

struct B { void f(); };

template<typename T>
struct A : virtual B { void f(); };

template<typename T>
struct C : virtual B, A<T> {
  void g() { this->f(); }
};

int main() { C<int> c; c.g(); }

Cela valide en C++03 code qui l'appelle, A<int>::f n'est pas valide en C++0x, parce que la recherche d'un nom lors de l'instanciation trouverez A<int>::f plutôt B::f, provoquant un conflit avec la définition de la recherche.

À ce stade, il n'est pas clair si c'est un défaut dans la FDIS. Le comité est conscient de cela et va évaluer la situation.


A l'aide de déclaration où la dernière partie est le même que l'identifiant dans la dernière partie de la qualification de la personne nom désignant une classe de base, que l'utilisation de la déclaration de maintenant les noms le constructeur, à la place des membres de ce nom.

Exemple:

struct A { protected: int B; };
typedef A B;

struct C : B {
  // inheriting constructor, instead of bringing A::B into scope
  using B::B;
};

int main() { C c; c.B = 0; }

L'exemple ci-dessus le code est bien formé en C++03, mais mal formé dans C++0x, A::B , est toujours inaccessible en main.

13voto

Xeo Points 69818

Comment est l'introduction de la conversion explicite des opérateurs d'une modification de rupture? L'ancienne version sera toujours seulement être "valide" comme avant.

Oui, le changement de l' operator void*() const de explicit operator bool() const sera une modification de rupture, mais uniquement s'il est utilisé d'une manière qui est faux dans et hors de lui-même. Conforme code ne sera pas rompu.

Maintenant, une autre modification importante est l'interdiction de réduire les conversions au cours d'agrégation d'initialisation:

int a[] = { 1.0 }; // error

Edit: Juste rememberer, std::identity<T> sera supprimée dans C++0x (voir la note). C'est pratique, struct pour faire des types dépendants. Depuis la struct vraiment ne fait pas beaucoup, cela devrait résoudre le problème:

template<class T>
struct identity{
  typedef T type;
};

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X