2015-12-19 3 views
12

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

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

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

+1

Можете ли вы озвучить свои предположения? –

+1

Я считаю, что это требуется даже в C++ 03. COW должно сохранить это свойство. – Puppy

+0

@Puppy: Извините, я сказал это неправильно. Лучше просто [посмотреть здесь] (http://stackoverflow.com/a/29199733/734069). Что-то вроде того. –

ответ

9

Новый совместимый с C++ 11 std::string был введен с новым (двойным) ABI в GCC 5 (Runtime Library Section of the changelog).

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

#if _GLIBCXX_USE_CXX11_ABI 

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

5
#include <string> 

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

int 
main() 
{ 
} 

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

Этот тест использует преимущества внутренней работы всех известных станд :: Lib реализаций std::string и реализации GCC в частности.

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

Для коротких строковых реализаций (в значительной степени предусмотренных C++ 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 бит), как по меньшей мере одна реализацию (libC++) меняет свои характеристики на эту аппаратную функцию. Затем он печатает 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/libstdC++ 4.8 явно не использует оптимизацию коротких строк. И только gcc/libstdC++ 4.8 имеет sizeof(string) == 1 word. И на самом деле это единственная реализация в этом опросе, использующая подсчет ссылок.

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

+0

Не могли бы вы вкратце объяснить, зачем это делать? У строк COW есть только один элемент данных 'void *' (private) и, конечно же, нет виртуальных функций? – vsoftco

+1

Хорошо, сделано ....... –

+0

Спасибо, отличное объяснение. – vsoftco