The other commenters so far have blamed name mangling. Name mangling isn't actually that big of a deal: to mangle most functions, just write out the fully-qualified name of the function/method, convert each component of the name individually via a simple function, and then tack on the mangling of the types for every argument. Name mangling can get hairy, but realistically, you're not going to be linking against a template using an unnamed lambda as a parameter.
The minor complication you get is that the C/C++ ecosystem uses char, short, int, long, and long long to determine types, while most other languages use a more sensible i8, i16, i32, i64 system. This means you can't use the native type system of your target language as the base for mangling, since i32 and i64 do not map cleanly to int, long, and long long. (Doesn't help either that pre-stdint.h libraries for defining target-independent i64 types may have chosen a different value for i64 than stdint.h).
The real problem is that a lot of the functions you would wish to call don't actually exist in the binary library you're linking against. Inline methods are frequently excluded as linkable targets, and you often don't want to link to them anyways, because they're meant to be inlined (think something like std::vector<T>::operator[]). On top of that, templated things are rarely instantiated (and have code generated for them) until their point of use).
Your list isn't even complete. Exception handling, deriving from C++ classes, RTTI etc. all add their own sets of challenges on top of what you have mentioned.
Because it's so flexible, low-level in some parts (memory management, raw pointers) and high-level in others (template metaprogramming, lambdas).
If you restrict the API to a subset of the language, you can make C++ ABI just fine. My favorite style is abstract interfaces.
For the GUI example, look at WinRT. It exposes very high-level functionality, expressed in C++ as IUnknown-derived interfaces. These interfaces can be consumed or implemented by any compilers, or even other languages.
Such APIs work well even for very performance-critical code like DirectX or Direct2D. But there's downside, such APIs is not the most idiomatic form of C++: no exceptions, no iterators or other template shenanigans, no RTTI, no standard collections not even strings. All that stuff needs to be replaced with some equivalents.
When I only have C++ clients, I don't usually inherit from IUnknown, instead making an abstract base class with virtual destructor, and using std::unique_ptr smart pointers instead of CComPTR.
Primarily it's due to function overloading. Different implementations may use different means to consistently and uniquely "mangle" function names on symbols to uniquely identify them in the library export. This mangling depends upon numerous factors, including parameter types and calling convention (if there are multiple conventions on a platform).