Une implémentation de bibliothèque unique C ++ 17 Plate-plateforme pour les identificateurs universellement uniques , simplement connaître sous le nom d'UUID ou de GUID (principalement sur Windows). Un UUID est un numéro 128 bits utilisé pour identifier de manière unique des informations dans les systèmes informatiques, tels que les clés de table de base de données, les interfaces COM, les classes et les bibliothèques de types, et bien d'autres.
Pour plus d'informations sur UUID / GUIDS, voir:
Bien que les spécifications mettent la bibliothèque UUID dans l'espace de noms std , cette implémentation utilise les uuids de l'espace de noms à cet effet, afin de rendre la bibliothèque utilisable sans violer les restrictions imposées à l'espace de noms std . Les types et services publics suivants sont disponibles:
Types de base:
| Nom | Description |
|---|---|
uuid | une classe représentant un UUID; Cela peut être construit par défaut (un Nil UUID), construit à partir d'une plage (définie par une paire d'itérateurs), ou à partir d'une span . |
uuid_variant | une énumération fortement de type représentant le type d'un UUID |
uuid_version | une énumération fortement de type représentant la version d'un UUID |
Générateurs:
| Nom | Description |
|---|---|
basic_uuid_random_generator | Un objet de fonction qui génère des Uuids de la version 4 à l'aide d'un moteur de générateur de nombres pseudo-aléatoires. |
uuid_random_generator | A basic_uuid_random_generator Utilisation du moteur Mersenne Twister ( basic_uuid_random_generator<std::mt19937> ) |
uuid_name_generator | Un objet de fonction qui génère la version 5, UUID basés sur le nom à l'aide de hachage SHA1. |
uuid_system_generator | Un objet de fonction qui génère de nouveaux UUID à l'aide de ressources du système d'exploitation ( CoCreateGuid sur Windows, uuid_generate sur Linux, CFUUIDCreate sur Mac)Remarque : Cela ne fait pas partie de la proposition standard. Il n'est disponible que si la macro UUID_SYSTEM_GENERATOR est définie. |
uuid_time_generator | Un objet de fonction expérimental qui génère des UUID basés sur le temps. Remarque : Il s'agit d'une fonctionnalité expérimentale et ne doit être utilisée dans aucun code de production. Il n'est disponible que si la macro UUID_TIME_GENERATOR est définie. |
Services publics:
| Nom | Description |
|---|---|
std::swap<> | Spécialisation de swap contre uuid |
std::hash<> | Spécialisation du hash pour uuid (nécessaire pour stocker des uuides dans des conteneurs associatifs non ordonnés, tels que std::unordered_set ) |
Constantes:
| Nom | Description |
|---|---|
uuid_namespace_dns | ID de l'espace de noms pour les uuids basés sur le nom lorsque la chaîne de nom est un nom de domaine entièrement qualifié. |
uuid_namespace_url | ID de l'espace de noms pour les uuids basés sur le nom lorsque la chaîne de nom est une URL. |
uuid_namespace_oid | ID de l'espace de noms pour les uuids basés sur le nom lorsque Mame String est un ISO OID (voir https://oidref.com/, https://en.wikipedia.org/wiki/Object_Identifier). |
uuid_namespace_x500 | ID de l'espace de noms pour les uuides basés sur le nom lorsque la chaîne de nom est un X.500 DN, au format de sortie de texte ou un texte (voir https://en.wikipedia.org/wiki/x.500, https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_one). |
Autre:
| Nom | Description |
|---|---|
operator== et operator!= | Pour la comparaison des uuides pour l'égalité / les inégalités |
operator< | Pour comparer si un UUID est inférieur à un autre. Bien que cette opération n'ait pas beaucoup de sens logique, elle est nécessaire pour stocker des UUID dans un ensemble std ::. |
operator<< | Pour écrire un UUID sur un flux de sortie en utilisant la représentation textuelle canonique. |
to_string() | Crée une chaîne avec la représentation textuelle canonique d'un UUID. |
Cette bibliothèque est une implémentation de la proposition P0959.
Au fur et à mesure que la proposition évolue sur la base du comité standard et des commentaires de la communauté C ++, cette mise en œuvre de la bibliothèque reflétera ces changements.
Voir l'histoire de la révision de la proposition d'histoire des changements.
Ce qui suit est une liste d'exemples d'utilisation de la bibliothèque:
Création d'un UUID NIL
uuid empty;
assert (empty.is_nil());Créer un nouvel 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);Création d'un nouvel UUID avec un générateur aléatoire par défaut
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);Création d'un nouvel UUID avec un générateur aléatoire particulier
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);Création d'un nouvel UUID avec le générateur de noms
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);Créer un UUID à partir d'une chaîne
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);Création d'un UUID à partir d'une séquence de 16 octets
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");Comparaison des uuides
uuid empty;
uuid id = uuids::uuid_system_generator{}();
assert (empty == empty);
assert (id == id);
assert (empty != id);Échanger des uuides
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());Conversion en chaîne
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");En utilisant avec un conteneur associatif ordonné
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());En utilisant dans un conteneur associatif non ordonné
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());Uuids de hachage
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)); Si vous générez des UUID à l'aide du basic_uuid_random_generator et STD :: Random_device pour semer un générateur, gardez à l'esprit que cela peut ne pas être non déterministe et générer réellement la même séquence de nombres:
STD :: Random_Device peut être implémenté en termes de moteur de nombres pseudo-aléatoires définis par l'implémentation si une source non déterministe (par exemple un périphérique matériel) n'est pas disponible pour l'implémentation. Dans ce cas, chaque objet std :: random_device peut générer la même séquence de nombres.
Cela pourrait être un problème avec Mingw. Voir Bug 85494 - L'implémentation de Random_Device sur Mingw est inutile. Cela a été fixé dans GCC 9.2.
Une alternative portable consiste à utiliser la bibliothèque Boost.Random.
La bibliothèque est prise en charge sur tous les principaux systèmes d'exploitation: Windows, Linux et Mac OS.
Si vous utilisez la bibliothèque dans un projet construit avec C ++ 20, vous pouvez utiliser std::span . Ceci est utilisé par défaut, si l'en-tête est pris en charge par votre compilateur. Le chèque est effectué avec la macro de fonction de fonction __CPPP_LIB_SPAN.
Sinon, comme lors de la construction avec C ++ 17, std::span n'est pas disponible. Cependant, la bibliothèque de support Microsoft Guidelines (AKA GSL) peut être utilisée pour son implémentation span (à partir de laquelle la version standard a été définie). La bibliothèque STDUUID utilise par défaut cette implémentation si std::span n'est pas disponible.
Pour vous assurer que gsl::span peut être utilisé, assurez-vous que la bibliothèque GSL est disponible et que le répertoire GSL inclue est répertorié dans les répertoires inclués pour le projet.
Si vous utilisez CMake pour créer le projet de test, assurez-vous que la variable appelée UUID_USING_CXX20_SPAN n'est pas définie, ou sa valeur est OFF (c'est la valeur par défaut). Cela garantira que le répertoire gsl sera inclus dans la liste de recherche des répertoires d'en-tête.
Un projet de test est disponible dans les sources. Pour construire et exécuter les tests, faites ce qui suit:
build dans le répertoire racine des sourcescmake .. à partir du répertoire build ; Si vous n'avez pas de CMake, vous devez d'abord l'installer.Exemples
Pour générer des fichiers de projet pour Visual Studio 2019, vous pouvez exécuter les commandes suivantes:
cd build
cmake -G "Visual Studio 17" -A x64 ..
Pour activer le système de fonctionnement du générateur UUID, définissez la variable UUID_SYSTEM_GENERATOR sur ON .
cd build
cmake -G "Visual Studio 17" -A x64 -DUUID_SYSTEM_GENERATOR=ON ..
Pour activer le générateur UUID expérimental basé sur le temps, définissez la variable UUID_TIME_GENERATOR sur ON .
cd build
cmake -G "Visual Studio 17" -A x64 -DUUID_TIME_GENERATOR=ON ..
L'implémentation SHA1 est basée sur la bibliothèque TinySha1.