2015-12-19 2 views
12

Ich schreibe einen C++ 11-Code, der Annahmen über die Natur von std::string macht, die gültig sind, aber das in C + geänderte Verhalten darstellen +11. In den früheren Tagen entsprach die Implementierung von libstdC++ basic_string den 98/03-Anforderungen, nicht jedoch den strengeren C++ 11-Anforderungen. Wie ich es verstehe, hat libstdC++ die Probleme um basic_string behoben. Das Problem besteht darin, dass viele Versionen der Bibliothek von Benutzern verwendet werden, die diesen Fix nicht implementieren. Und mein Code kann im Stillen auf viele unangenehme Arten auf ihnen versagen.Testen, ob die Version von libstdC++ eine C++ 11-konforme std :: string verwendet

Ich möchte ein static_assert Feuer haben, wenn der Benutzer versucht, meine Bibliothek gegen diese nicht-konforme Versionen von libstdC++ zu kompilieren. Wie erkenne ich die Version und, was genauso wichtig ist, welche Version sollte ich suchen?

+1

können Sie Ihre Annahmen äußern? –

+1

Ich glaube, das ist sogar in C++ 03 erforderlich. COW sollte diese Eigenschaft behalten. – Puppy

+0

@Puppy: Entschuldigung, ich sagte das falsch. Es ist besser, einfach [siehe hier] (http://stackoverflow.com/a/29199733/734069). So ähnlich. –

Antwort

9

Das neue C++ 11-konforme std::string wurde mit dem neuen (doppelten) ABI in GCC 5 (Runtime Library Section of the changelog) eingeführt.

Das Makro _GLIBCXX_USE_CXX11_ABI entscheidet, ob die alte oder neue ABI verwendet wird, so dass nur sie überprüfen:

#if _GLIBCXX_USE_CXX11_ABI 

Natürlich, die spezifisch ist nur libstdC++.

5
#include <string> 

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

int 
main() 
{ 
} 

Demo: http://melpon.org/wandbox/permlink/P8LB79Cy6ASZlKuV

Dieser Test nutzt die internen Abläufe alle bekannten std :: lib Implementierungen von std::string und der Umsetzung des gcc im Besonderen.

gcc's refcounted string besteht aus einem einzigen Zeiger auf eine dynamisch zugewiesene Struktur, die die Größe, Kapazität, Referenzzahl und Daten der Zeichenfolge enthält. Scott Meyers gibt eine schöne Zusammenfassung von String-Implementierungen in Effective STL, die im Zeitrahmen von 2001 korrekt waren. Ich glaube (ich könnte mich irren), dass "Implementierung C" in Punkt 15 dieses Buches gcc's std :: string ist.

Für kurze String-Implementierungen (so ziemlich von C++ 11 vorgeschrieben), kann ein string nicht länger aus einem einzigen Zeiger auf dem Stapel bestehen. Scotts Implementierung D ist unser erster Blick auf eine kurze String-Implementierung aus dieser Ära. Dies ist die VS/Dinkumware string. Die sizeof(string) selbst wird einige Datenpuffer enthalten, um String-Daten ohne Zuordnungen zu speichern.

Man kann den Griff bekommen, was verschiedene Implementierungen sind mit diesem Kurzprogramm tun:

#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'; 
} 

Dieser druckt die Wortgröße, typischerweise 4 oder 8 (32 Bit/64 Bit) als mindestens eine Implementierung (libC++) ändert seine Eigenschaften auf dieser Hardware-Funktion. Dann druckt es die sizeof(string), die ein Vielfaches der Wortgröße sein wird, und dann die capacity() eines leeren string, die die Größe des Short-String-Puffers sein wird, wenn es existiert.

ist hier ein etwas unvollständig Umfrage:

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 

In dieser Umfrage verwendet nur gcc/libstdC++ 4.8 eindeutig keine Short-String-Optimierung. Und nur gcc/libstdC++ 4.8 hat sizeof(string) == 1 word. Und dies ist in der Tat die einzige Implementierung in dieser Umfrage, die Referenzzählung verwendet.

Alles in allem ist dieser Test für libstdC++ std::string nicht tragbar. Aber nach Spezifikation muss es nicht sein. Wir können die bekannte Geschichte der Entwicklung von gcc in diesem Bereich nutzen. Die Spezifikation (die Frage) besagt, dass sie nur auf gcc's libstdC++ funktionieren muss.

+0

Können Sie kurz erklären, warum das der Trick ist? Haben COW-Strings nur ein 'void *' (privates) Datenelement und natürlich keine virtuellen Funktionen? – vsoftco

+1

Ok, fertig ....... –

+0

Danke, tolle Erklärung. – vsoftco

Verwandte Themen