Подтвердить что ты не робот

Проверьте, использует ли версия libstdС++ С++ 11-совместимый std::string

Я пишу код С++ 11, который делает предположения о природе std::string действительными, но представляет собой поведение, которое было изменено на С++ 11. В более ранние дни реализация libstdС++ basic_string соответствовала требованиям 98/03, но не к более строгим требованиям С++ 11.

Как я понимаю, libstdС++ исправил проблемы вокруг basic_string. Проблема в том, что существует множество версий библиотеки, которые используют пользователи, которые не реализуют это исправление. И мой код может бесшумно терпеть неудачу на них.

Я хотел бы иметь огонь static_assert, если пользователь пытается скомпилировать мою библиотеку с этими несоответствующими версиями libstdС++. Как определить версию и, что не менее важно, какую версию я должен искать?

4b9b3361

Ответ 1

Новый совместимый с С++ 11 std::string был введен с новым (двойным) ABI в GCC 5 (разделе Runtime Library в журнале изменений).

Макрос _GLIBCXX_USE_CXX11_ABI определяет, используется ли старый или новый ABI, поэтому просто проверьте его:

#if _GLIBCXX_USE_CXX11_ABI

Конечно, это специфично только для libstdС++.

Ответ 2

#include <string>

static_assert(sizeof(std::string) != sizeof(void*), "using ref-counted string");

int
main()
{
}

Демо: http://melpon.org/wandbox/permlink/P8LB79Cy6ASZlKuV

В этом тесте используются внутренние работы всех известных реализаций std:: lib std::string и gcc-реализации в частности.

gcc refcounted string состоит из одного указателя на динамически распределенную структуру, которая содержит размер, емкость, счетчик ссылок и данные строки. Скотт Мейерс делает хорошее резюме строковых реализаций в Effective STL, которое было точным в 2001 году. Я считаю (я мог ошибаться), что "реализация C" в пункте 15 этой книги - gcc std::string.

Для коротких строковых реализаций (в значительной степени предусмотренных С++ 11), string больше не может состоять из одного указателя на стеке. Внедрение Скотта D - это наш первый взгляд на реализацию коротких строк с той эпохи. Это VS/Dinkumware string. Сам sizeof(string) будет содержать некоторый буфер данных для хранения строковых данных без выделения.

Можно получить дескриптор того, что различные реализации делают с этой короткой программой:

#include <iostream>
#include <string>

int
main()
{
    std::string s;
    std::cout << "word size is           " << sizeof(void*)/sizeof(char) << '\n';
    std::cout << "sizeof string is       " << sizeof(s) << '\n';
    std::cout << "short string buffer is " << s.capacity() << '\n';
}

Это печатает размер слова, обычно 4 или 8 (32 бит /64 бит), поскольку по крайней мере одна реализация (libС++) меняет свои характеристики на этой аппаратной функции. Затем он печатает sizeof(string), который будет кратно размеру слова, а затем capacity() пустого string, который будет размером буфера короткой строки, если он существует.

Вот несколько неполный обзор:

gcc/libstdc++ 4.8

word size is           8
sizeof string is       8
short string buffer is 0

gcc/libstdc++ 5.2

word size is           8
sizeof string is       32
short string buffer is 15

clang/libc++ -arch i386 OS X

word size is           4
sizeof string is       12
short string buffer is 10

clang/libc++ -arch x86_64 OS X

word size is           8
sizeof string is       24
short string buffer is 22

VS-2015

word size is           4
sizeof string is       24
short string buffer is 15

В этом опросе только gcc/libstdС++ 4.8 явно не использует оптимизацию коротких строк. И только gcc/libstdС++ 4.8 имеет sizeof(string) == 1 word. И это на самом деле единственная реализация в этом опросе, которая использует подсчет ссылок.

В целом, этот тест для libstdС++ std::string не переносится. Но по спецификации это не обязательно. Мы можем воспользоваться известной историей разработки gcc в этой области. Спецификация (вопрос) говорит, что она должна работать только с gcc libstdС++.