What breaking changes are introduced in C++11?

后端 未结 9 1653
陌清茗
陌清茗 2020-11-22 14:34

I know that at least one of the changes in C++11 that will cause some old code to stop compiling: the introduction of explicit operator bool() in the standard l

相关标签:
9条回答
  • 2020-11-22 15:19

    Some core incompatibilities that are not covered by the incompatibilities section:


    C++0x treats the injected class name as a template, if the name is passed as an argument to a template template parameter, and as a type if it is passed to a template type parameter.

    Valid C++03 code may behave differently if it relies on the injected class name to be always a type in these scenarios. Example code taken from my 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();
    }
    

    In C++03, the code calls the second g both times.


    C++0x makes some names that were dependent in C++03 to be now non-dependent. And requires name lookup for non-dependent qualified names that refer to members of the current class template to be repeated at instantiation, and requires verification that these names lookup the same way as done at the template definition context.

    Valid C++03 code that depends on the dominance rule may now not compile anymore because of this change.

    Example:

    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(); }
    

    This valid C++03 code that calls A<int>::f is not valid in C++0x, because name lookup when instantiating will find A<int>::f as opposed to B::f, causing a conflict with the at-definition lookup.

    At this point, it is not clear whether that is a defect in the FDIS. The committee is aware of this and will evaluate the situation.


    A using declaration where the last part is the same as the identifier in the last part of the qualifier in the qualified name denoting a base class, that using declaration now names the constructor, instead of members with that name.

    Example:

    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; }
    

    The above example code is well-formed in C++03, but ill-formed in C++0x, as A::B is still inaccessible in main.

    0 讨论(0)
  • 2020-11-22 15:24

    How is the introduction of explicit conversion operators a breaking change? The old version will still just be as "valid" as before.

    Yes, the change from operator void*() const to explicit operator bool() const will be a breaking change, but only if it is used in a way that is wrong in and out of itself. Conforming code won't be broken.

    Now, another breaking change is the banning of narrowing conversions during aggregate initialization:

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

    Edit: Just rememberer, std::identity<T> will be removed in C++0x (see the note). It's a convenience struct to make types dependent. Since the struct really doesn't do much, this should fix it:

    template<class T>
    struct identity{
      typedef T type;
    };
    
    0 讨论(0)
  • 2020-11-22 15:26

    The meaning of the auto keyword changed.

    0 讨论(0)
  • 2020-11-22 15:28

    Stream extraction failure is treated differently.

    Example

    #include <sstream>
    #include <cassert>
    
    int main()
    {
       std::stringstream ss;
       ss << '!';
       
       int x = -1;
       
       assert(!(ss >> x)); // C++03 and C++11
       assert(x == -1);    // C++03
       assert(x == 0);     // C++11
    }
    

    Change proposal

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3246.html#23

    Standard reference

    [C++03: 22.2.2.1.2/11]: The result of stage 2 processing can be one of

    • A sequence of chars has been accumulated in stage 2 that is converted (according to the rules of scanf) to a value of the type of val. This value is stored in val and ios_base::goodbit is stored in err.
    • The sequence of chars accumulated in stage 2 would have caused scanf to report an input failure. ios_base::failbit is assigned to err. [ed: Nothing is stored in val.]

    [C++11: 22.4.2.1.2/3]: [..] The numeric value to be stored can be one of:

    • zero, if the conversion function fails to convert the entire field. ios_base::failbit is assigned to err.
    • the most positive representable value, if the field represents a value too large positive to be represented in val. ios_base::failbit is assigned to err.
    • the most negative representable value or zero for an unsigned integer type, if the field represents a value too large negative to be represented in val. ios_base::failbit is assigned to err.
    • the converted value, otherwise.

    The resultant numeric value is stored in val.

    Implementations

    • GCC 4.8 correctly outputs for C++11:

      Assertion `x == -1' failed

    • GCC 4.5-4.8 all output for C++03 the following, which would appear to be a bug:

      Assertion `x == -1' failed

    • Visual C++ 2008 Express correctly outputs for C++03:

      Assertion failed: x == 0

    • Visual C++ 2012 Express incorrectly outputs for C++11, which would appear to be a status-of-implementation issue:

      Assertion failed: x == 0

    0 讨论(0)
  • 2020-11-22 15:29
    struct x {
       x(int) {}
    };
    
    void f(auto x = 3) { }
    
    int main() {
       f();
    }
    

    C++03: valid.

    C++0x: error: parameter declared 'auto'

    0 讨论(0)
  • 2020-11-22 15:31

    There are numerous changes to the containers library that allow more efficient code but silently break backwards compatibility for a few corner cases.

    Consider, for example, std::vector, default construction, C++0x, and breaking changes.

    0 讨论(0)
提交回复
热议问题