I'm writing some C++11 code that makes assumptions about the nature of std::string
that are valid, but represent behavior that was changed in C++11. In the earlier days, libstdc++'s basic_string
implementation conformed to the 98/03 requirements, but not to the more strict C++11 requirements.
As I understand it, libstdc++ has fixed the issues around basic_string
. The problem is that there are many versions of the library that people use which do not implement this fix. And my code may silently fail in many unpleasant ways on them.
I would like to have a static_assert
fire if the user attempts to compile my library against those non-conformant versions of libstdc++. How do I detect the version, and equally importantly, which version should I look for?
The new C++11 compliant
std::string
was introduced with the new (dual) ABI in GCC 5 (Runtime Library Section of the changelog).The macro
_GLIBCXX_USE_CXX11_ABI
decides whether the old or new ABI is being used, so just check it:Of course that's specific to libstdc++ only.
Demo: http://melpon.org/wandbox/permlink/P8LB79Cy6ASZlKuV
This test takes advantage of the internal workings of all of the known std::lib implementations of
std::string
, and of gcc's implementation in particular.gcc's refcounted
string
consists of a single pointer to a dynamically allocated structure that holds the size, capacity, reference count, and data of the string. Scott Meyers does a nice summary of string implementations in Effective STL that was accurate in the 2001 time frame. I believe (I could be mistaken) that "implementation C" in item 15 of that book is gcc's std::string.For short-string implementations (pretty much mandated by C++11), a
string
can no longer consist of a single pointer on the stack. Scott's implementation D is our first look at a short-string implementation from that era. This is the VS/Dinkumwarestring
. Thesizeof(string)
itself will contain some data buffer to hold string data with no allocations.One can get a handle on what different implementations are doing with this short program:
This prints out the word size, typically 4 or 8 (32 bit / 64 bit) as at least one implementation (libc++) changes its characteristics on this hardware feature. Then it prints out the
sizeof(string)
which will be a multiple of word size, and then thecapacity()
of an emptystring
, which will be the size of the short-string buffer if it exists.Here is a somewhat incomplete survey:
In this survey, only gcc/libstdc++ 4.8 is clearly not using a short-string optimization. And only gcc/libstdc++ 4.8 has
sizeof(string) == 1 word
. And this is in fact the only implementation in this survey that is using reference counting.All in all, this test for libstdc++'s
std::string
isn't portable. But by specification it doesn't have to be. We can take advantage of the known history of gcc's development in this area. The spec (the question) says it only has to work on gcc's libstdc++.