>Travis Vitek wrote > >Martin Sebor wrote: >> >> I've incorporated everyone's feedback and committed an updated >> version with a number of enhancements of my own. Among the most >> important are the new Goals section with suggested frequencies of >> releases, and the integration of the Version Policy (I plan to delete >> versions.html). Let me know what you think. >> >> http://incubator.apache.org/stdcxx/releases.html >> > >Martin, > >I found this page that documents a few do's and dont's of binary >compatibility. I realize that most of the tricky issues involve inline >functions or templates, but this gives a list of the common pitfalls. > > http://tinyurl.com/2gf38p > >Travis
Here are some examples that I came up with. Each case is written in a pseudo diff format. Travis // neither source nor binary compatible. not source compatible // if user might take address of member function A::f. struct A { - int f() const { return 1; } + int f(int i = 1) const { return i; } }; // alternative is source and binary compatible. can be changed // to a default argument in next source incompatible release. struct A { int f() const { return 1; } + int f(int i) const { return i; } }; // is binary compatible, but not be source compatible because // the compiler has no way to handle A().f(1) struct A { int f(long i) const { return 2; } + int f(unsigned i) const { return 2; } }; // not binary compatible, changing access specifier on windows is a no-no. if the // new access modifier is more restricted, this may be source incompatible, but // only if the user code calls or takes the address of the function. class A { -private: +public: int f() const { return 1; } }; // source and binary compatible, not functionally compatible. f() will square v // in user code, and ctor will square v in library code. if an instance is // created in library and passed to user code, it will be squared twice. if the // other way, it will not be squared at all. // // if the definitions were outlined, this would be compatible. class A { public: - A(float f) : v(f) { } - float f() const { return v*v; } + A(float f) : v(f*f) { } + float f() const { return v; } private: float v; }; // binary and source compatible, but not functionally compatible // because call to g() is inlined. // // this would be compatible if f() were outlined, or g() behaved // the same for input values 2 and 3. struct A { - void f() { g(2); } + void f() { g(3); } void g(int i); }; // it appears that this could be fully compatible in some cases. // it might not be source/functionally compatible if the user is // exposed to this type. a switch on an E instance might cause a // default block to be hit, which could trigger a failure in user // code. // // if A::Z is used as a `last enum' marker, this might introduce // a binary compatibility issue if a global or member array is // declared to have A::Z elements. // // this might also be binary incompatible if the enum is persisted. struct A { - enum E { W, X, Z }; + enum E { W, X, Y, Z }; };