I've put together the following description of C++98/11 ABI (in)compatibility, so people can tell which libraries need to be recompiled. This is useful when you've bought a library that didn't come with source code, and you're trying to figure out if you need to buy a new version. I think this belongs on the Wiki somewhere, but I wanted to run it by the list first to make sure it's accurate. You can probably skip the first section, since it's just a description of how to use the subsequent list.
This page explains how to identify when your pre-compiled library (.a or .so) defines a symbol that has a different enough definition in C++98 vs C++11 that it could cause runtime problems if it's linked into a program compiled for the other version. First, get a list of demangled symbols from your .a or .so: $ (find . -name '*.a'|xargs nm -f posix; find . -name '*.so' | xargs nm -f posix -D)|cut -f1 -d' '|LANG=C sort -u|c++filt|sort (There may be better ways to get this list.) Next, find instances in this list of the ABI changes listed below. For example, you might find: std::_List_base<FooBar, std::allocator<FooBar> >::_M_clear() Since std::_List_base::_M_clear() destroys nodes, it's affected by the addition of the _M_size field and can't be used by C++11 code if it was compiled for C++98, or vice versa. If it's possible that code outside the library would use this instance of _List_base, then you have to recompile the library. On the other hand, if FooBar is a type used only inside this library, then code using the library is safe. If FooBar is defined by the library but exposed in one of the library's headers, then the library still needs to be recompiled, since code using it could wind up including the other version's implementation. === ABI Changes === complex::{real,imag}(), std::{real,imag}(complex) The non-const overloads go from returning _Tp& to _Tp. [Since gcc-4.4] std::list, std::_List_impl, and std::_List_base New _M_size member, meaning any method that adds or removes nodes or inspects the size has a new ABI. [Since gcc-4.7] std::operator-(reverse_iterator) and std::operator-(__normal_iterator) may return a different type if reverse_iterator<_IteratorL>::difference_type (respectively, __normal_iterator<_IteratorL, _Container>::difference_type) isn't accurate. [Since gcc-4.4] map::erase(iterator), multimap::erase(iterator), set::erase(const_iterator), set::erase(const_iterator, const_iterator), multiset::erase(const_iterator), multiset::erase(const_iterator, const_iterator): Return type changes from void to iterator. [Since gcc-4.5] _Rb_tree<T, T>::erase(const_iterator), _Rb_tree<T, T>::erase(const_iterator, const_iterator), _Rb_tree<T, pair>::erase(iterator): Return type changes from void to iterator. these are instantiated from map and set. [Since gcc-4.5] vector::data()'s return type changes from pointer to _Tp* This is a no-op with most allocators, but any allocator that defines a non-default pointer typedef will be incompatible. [Since gcc-4.6] Probably safe: istreambuf_iterator::reference changes from _CharT& to _CharT. This could affect return types if they mention 'reference', but they appear not to mention it when istreambuf_iterator is involved. [Since gcc-4.7] Probably safe: map::erase(iterator, iterator), multimap::erase(iterator, iterator) C++11 uses const_iterator, which doesn't collide. Other versions of gcc are unlikely to have defined this overload in C++98 mode, and C++11 is unlikely to have defined the iterator version. [Since gcc-4.5] Probably safe: Types with node allocators, like deque and tree C++11 uses _M_get_Node_allocator().construct(node, ...), while C++98 uses get_allocator().construct(node->_M_value_field, ...). The node's constructor forwards to the value_field's constructor, so this works by default. Can this cause problems with some mix of C++98/C++11 allocator compilations? I haven't analyzed the debug and profile headers. I found these differences by grepping for GXX_EXPERIMENTAL_CXX0X inside libstdc++, and examining each instance to see if there was an #else clause that had different behavior in C++11 vs C++98. === ABI non-changes === libstdc++'s binary component is nearly ABI-compatible between C++98 and C++11. Most incompatibilities are in the templates defined in headers, but the complex<> stream operators call the real() and imag() methods that change return type. If these calls aren't inlined, (and they're likely to be inlined), then libstdc++ (which is compiled in C++98 mode by default) could cause problems when linked into C++11 programs. (http://gcc.gnu.org/PR53429) There have been some claims that the change in the definition of POD types causes an ABI incompatibility, but apparently it doesn't in practice: http://gcc.gnu.org/ml/gcc/2012-01/msg00056.html.