Eine C ++ 17-plattformübergreifende Einzelhoch-Bibliotheksimplementierung für universell eindeutige Kennungen , einfach als uuid oder GUID (hauptsächlich unter Windows) bekannt. Eine UUID ist eine 128-Bit-Nummer, mit der Informationen in Computersystemen wie Datenbanktabellenschlüssel, COM-Schnittstellen, Klassen und Typbibliotheken und viele andere eindeutig identifiziert werden.
For information about UUID/GUIDs see:
Obwohl in der Spezifikation die UUID -Bibliothek in den std -Namespace eingebaut wird, verwendet diese Implementierung den Namespace uuids für diesen Zweck, um die Bibliothek verwendbar zu machen, ohne die im std -Namespace auferlegten Beschränkungen zu verletzen. The following types and utilities are available:
Basic types:
| Name | Beschreibung |
|---|---|
uuid | a class representing a UUID; this can be default constructed (a nil UUID), constructed from a range (defined by a pair of iterators), or from a span . |
uuid_variant | a strongly type enum representing the type of a UUID |
uuid_version | a strongly type enum representing the version of a UUID |
Generators:
| Name | Beschreibung |
|---|---|
basic_uuid_random_generator | a function object that generates version 4 UUIDs using a pseudo-random number generator engine. |
uuid_random_generator | a basic_uuid_random_generator using the Mersenne Twister engine ( basic_uuid_random_generator<std::mt19937> ) |
uuid_name_generator | a function object that generates version 5, name-based UUIDs using SHA1 hashing. |
uuid_system_generator | Ein Funktionsobjekt, das neue UUIDs mithilfe von Betriebssystemressourcen generiert ( CoCreateGuid unter Windows, uuid_generate unter Linux, CFUUIDCreate auf dem Mac)Note : This is not part of the standard proposal. It is available only if the UUID_SYSTEM_GENERATOR macro is defined. |
uuid_time_generator | an experimental function object that generates time-based UUIDs. Note :This is an experimental feature and should not be used in any production code. Es ist nur verfügbar, wenn das Makro UUID_TIME_GENERATOR definiert ist. |
Versorgungsunternehmen:
| Name | Beschreibung |
|---|---|
std::swap<> | Spezialisierung des swap gegen uuid |
std::hash<> | Spezialisierung von hash für uuid (notwendig, um UUIDs in nicht ordnungsgemäßen assoziativen Behältern zu speichern, wie std::unordered_set |
Konstanten:
| Name | Beschreibung |
|---|---|
uuid_namespace_dns | Namespace-ID für Namensbasis UUIDs Wenn die Namenszeichenfolge ein vollständig qualifizierter Domänenname ist. |
uuid_namespace_url | Namespace-ID für Namensbasis uUids Wenn die Namenszeichenfolge eine URL ist. |
uuid_namespace_oid | Namespace-ID für Namensbasis UUIDs Wenn Mame String ein ISO OID ist (siehe https://oidref.com/, https://en.wikipedia.org/wiki/object_identifier). |
uuid_namespace_x500 | Namespace-ID für Namensbasiertes UUIDs Wenn der Name Zeichenfolge ein X.500 DN ist, in der oder einem Textausgabeformat (siehe https://en.wikipedia.org/wiki/x.500, https://en.wikipedia.org/wiki/abstract_nota_notation_one). |
Andere:
| Name | Beschreibung |
|---|---|
operator== und operator!= | Für UUIDS -Vergleiche für Gleichheit/Ungleichheit |
operator< | Zum Vergleich, ob eine UUIDS geringer ist als ein anderer. Obwohl diese Operation nicht viel logisch Sinn macht, ist sie notwendig, um UUIDs in einem STD :: Set zu speichern. |
operator<< | Um eine UUID mit der kanonischen Textdarstellung in einen Ausgabestream zu schreiben. |
to_string() | Erstellt eine Zeichenfolge mit der kanonischen Textdarstellung eines UUID. |
Diese Bibliothek ist eine Implementierung des Vorschlags P0959.
Während sich der Vorschlag auf der Grundlage des Standardausschusses und des C ++ - Community -Feedbacks entwickelt, spiegelt diese Umsetzung der Bibliothek diese Änderungen wider.
Siehe die Revisionsgeschichte des Vorschlags für die Geschichte der Änderungen.
Das Folgende ist eine Liste von Beispielen für die Verwendung der Bibliothek:
Erstellen eines Nil Uuid
uuid empty;
assert (empty.is_nil());Erstellen einer neuen UUID
uuid const id = uuids::uuid_system_generator{}();
assert (!id.is_nil());
assert (id.version() == uuids::uuid_version::random_number_based);
assert (id.variant() == uuids::uuid_variant::rfc);Erstellen eines neuen UUID mit einem Standard -Zufallsgenerator
std::random_device rd;
auto seed_data = std::array< int , std::mt19937::state_size> {};
std::generate (std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq (std::begin(seed_data), std::end(seed_data));
std::mt19937 generator (seq);
uuids::uuid_random_generator gen{generator};
uuid const id = gen();
assert (!id.is_nil());
assert (id.as_bytes().size() == 16);
assert (id.version() == uuids::uuid_version::random_number_based);
assert (id.variant() == uuids::uuid_variant::rfc);Erstellen eines neuen UUID mit einem bestimmten Zufallsgenerator
std::random_device rd;
auto seed_data = std::array< int , 6 > {};
std::generate (std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq (std::begin(seed_data), std::end(seed_data));
std::ranlux48_base generator (seq);
uuids::basic_uuid_random_generator<std::ranlux48_base> gen (&generator);
uuid const id = gen();
assert (!id.is_nil());
assert (id.as_bytes().size() == 16);
assert (id.version() == uuids::uuid_version::random_number_based);
assert (id.variant() == uuids::uuid_variant::rfc);Erstellen eines neuen UUID mit dem Namensgenerator
uuids::uuid_name_generator gen (uuids::uuid::from_string( " 47183823-2574-4bfd-b411-99ed177d3e43 " ).value());
uuid const id = gen( " john " );
assert (!id.is_nil());
assert (id.version() == uuids::uuid_version::name_based_sha1);
assert (id.variant() == uuids::uuid_variant::rfc);Erstellen Sie eine UUID aus einer Zeichenfolge
auto str = " 47183823-2574-4bfd-b411-99ed177d3e43 " s;
auto id = uuids::uuid::from_string(str);
assert (id.has_value());
assert (uuids::to_string(id.value()) == str);
// or
auto str = L" 47183823-2574-4bfd-b411-99ed177d3e43 " s;
uuid id = uuids::uuid::from_string(str).value();
assert (uuids::to_string< wchar_t >(id) == str);Erstellen einer UUID aus einer Sequenz von 16 Bytes
std::array<uuids::uuid::value_type, 16 > arr{{
0x47 , 0x18 , 0x38 , 0x23 ,
0x25 , 0x74 ,
0x4b , 0xfd ,
0xb4 , 0x11 ,
0x99 , 0xed , 0x17 , 0x7d , 0x3e , 0x43 }};
uuid id (arr);
assert (uuids::to_string(id) == "47183823-2574-4bfd-b411-99ed177d3e43");
// or
uuids::uuid::value_type arr[ 16 ] = {
0x47 , 0x18 , 0x38 , 0x23 ,
0x25 , 0x74 ,
0x4b , 0xfd ,
0xb4 , 0x11 ,
0x99 , 0xed , 0x17 , 0x7d , 0x3e , 0x43 };
uuid id (std::begin(arr), std::end(arr));
assert (uuids::to_string(id) == "47183823-2574-4bfd-b411-99ed177d3e43");
// or
uuids::uuid id{{
0x47 , 0x18 , 0x38 , 0x23 ,
0x25 , 0x74 ,
0x4b , 0xfd ,
0xb4 , 0x11 ,
0x99 , 0xed , 0x17 , 0x7d , 0x3e , 0x43 }};
assert (uuids::to_string(id) == "47183823-2574-4bfd-b411-99ed177d3e43");Vergleich von Uuiden
uuid empty;
uuid id = uuids::uuid_system_generator{}();
assert (empty == empty);
assert (id == id);
assert (empty != id);Uuiden austauschen
uuid empty;
uuid id = uuids::uuid_system_generator{}();
assert (empty.is_nil());
assert (!id.is_nil());
std::swap (empty, id);
assert (!empty.is_nil());
assert (id.is_nil());
empty.swap(id);
assert (empty.is_nil());
assert (!id.is_nil());Konvertieren in String
uuid empty;
assert (uuids::to_string(empty) == "00000000-0000-0000-0000-000000000000");
assert (uuids::to_string< wchar_t >(empty) == L"00000000-0000-0000-0000-000000000000");Verwendung mit einem bestellten assoziativen Container
std::random_device rd;
auto seed_data = std::array< int , std::mt19937::state_size> {};
std::generate (std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq (std::begin(seed_data), std::end(seed_data));
std::mt19937 engine (seq);
uuids::uuid_random_generator gen (&engine);
std::set<uuids::uuid> ids{uuid{}, gen (), gen (), gen (), gen ()};
assert (ids.size() == 5);
assert (ids.find(uuid{}) != ids.end());Verwendung in einem ungeordneten assoziativen Container
std::random_device rd;
auto seed_data = std::array< int , std::mt19937::state_size> {};
std::generate (std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq (std::begin(seed_data), std::end(seed_data));
std::mt19937 engine (seq);
uuids::uuid_random_generator gen (&engine);
std::unordered_set<uuids::uuid> ids{uuid{}, gen (), gen (), gen (), gen ()};
assert (ids.size() == 5);
assert (ids.find(uuid{}) != ids.end());Hashing Uuiden
using namespace std ::string_literals ;
auto str = " 47183823-2574-4bfd-b411-99ed177d3e43 " s;
uuid id = uuids::uuid::from_string(str).value();
auto h1 = std::hash<std::string>{};
auto h2 = std::hash<uuid>{};
assert (h1(str) == h2(id)); Wenn Sie UUIDs mit dem basic_uuid_random_generator und std :: random_device generieren, um einen Generator zu säen, dann beachten Sie, dass dies möglicherweise nicht nicht deterministisch ist und tatsächlich die gleiche Abfolge von Zahlen erzeugt:
STD :: Random_Device kann in Bezug auf eine implementierungsdefinierte Pseudo-Random-Nummer-Engine implementiert werden, wenn eine nicht detministische Quelle (z. B. ein Hardware-Gerät) der Implementierung nicht verfügbar ist. In diesem Fall kann jedes STD :: Random_Device -Objekt dieselbe Zahlenfolge generieren.
Dies könnte ein Problem mit Mingw sein. Siehe Bug 85494 - Die Implementierung von Random_Device auf Mingw ist nutzlos. Dies wurde in GCC 9.2 festgelegt.
Eine tragbare Alternative besteht darin, die Bibliothek Boost.random zu verwenden.
Die Bibliothek wird in allen wichtigen Betriebssystemen unterstützt: Windows, Linux und Mac OS.
Wenn Sie die Bibliothek in einem mit C ++ 20 erstellten Projekt verwenden, können Sie std::span verwenden. Dies wird standardmäßig verwendet, wenn der Header von Ihrem Compiler unterstützt wird. Die Überprüfung erfolgt mit dem Feature-Test __cpp_lib_span.
Andernfalls ist std::span nicht verfügbar, z. B. beim Bauen mit C ++ 17. Die Microsoft Guidelines Support Library (auch bekannt als GSL) kann jedoch für die span -Implementierung verwendet werden (aus der die Standardversion definiert wurde). Die STDUUID -Bibliothek stellt es aus, diese Implementierung zu verwenden, wenn std::span nicht verfügbar ist.
Um sicherzustellen, dass gsl::span verwendet werden kann, stellen Sie sicher, dass die GSL -Bibliothek verfügbar ist und das GSL -Include -Verzeichnis in den Verzeichnissen für das Projekt aufgeführt ist.
Wenn Sie CMAKE zum Erstellen des Testprojekts verwenden, stellen Sie sicher, dass die Variable, die als UUID_USING_CXX20_SPAN bezeichnet wird, nicht definiert ist oder der Wert OFF (dies ist der Standardwert). Dadurch wird sichergestellt, dass das gsl -Verzeichnis in die Suchliste der Header -Verzeichnisse aufgenommen wird.
In den Quellen ist ein Testprojekt verfügbar. Um die Tests zu erstellen und auszuführen, führen Sie Folgendes aus:
build -Verzeichnis im Stammverzeichnis der Quellencmake .. aus dem build -Verzeichnis aus; Wenn Sie keine CMake haben, müssen Sie es zuerst installieren.Beispiele
Um Projektdateien für Visual Studio 2019 zu generieren, können Sie die folgenden Befehle ausführen:
cd build
cmake -G "Visual Studio 17" -A x64 ..
So aktivieren Sie das Betriebssystem UUID -Generator setzen Sie die Variable UUID_SYSTEM_GENERATOR auf ON .
cd build
cmake -G "Visual Studio 17" -A x64 -DUUID_SYSTEM_GENERATOR=ON ..
So aktivieren Sie den experimentellen zeitbasierten UUID-Generator, setzen Sie die Variable UUID_TIME_GENERATOR auf ON .
cd build
cmake -G "Visual Studio 17" -A x64 -DUUID_TIME_GENERATOR=ON ..
Die SHA1 -Implementierung basiert auf der TinySHA1 -Bibliothek.