Una implementación de la biblioteca de una sola plataforma C ++ 17 para identificadores universalmente únicos , simplemente conoce como UUID o GUID (principalmente en Windows). Un UUID es un número de 128 bits utilizado para identificar de manera única la información en sistemas informáticos, como claves de mesa de bases de datos, interfaces COM, clases y bibliotecas de tipo, y muchas otras.
Para obtener información sobre UUID/GUIDS, ver:
Aunque la especificación coloca la biblioteca UUID en el espacio de nombres std , esta implementación utiliza los uuids del espacio de nombres para este propósito, para que la biblioteca se pueda usar sin violar las restricciones impuestas en el espacio de nombres std . Los siguientes tipos y servicios públicos están disponibles:
Tipos básicos:
| Nombre | Descripción |
|---|---|
uuid | una clase que representa un uuid; Esto se puede construir por defecto (un uuid nil), construido a partir de un rango (definido por un par de iteradores) o desde un span . |
uuid_variant | un enum de tipo fuertemente que representa el tipo de UUID |
uuid_version | un enum de tipo fuertemente que representa la versión de un uuid |
Generadores:
| Nombre | Descripción |
|---|---|
basic_uuid_random_generator | Un objeto de función que genera UUID de la versión 4 utilizando un motor de generador de números pseudo-aleatorio. |
uuid_random_generator | Un basic_uuid_random_generator USANDO EL MOTOR MERSENNE THISTER ( basic_uuid_random_generator<std::mt19937> )) |
uuid_name_generator | Un objeto de función que genera UUID basados en nombres de la versión 5 utilizando el hash SHA1. |
uuid_system_generator | Un objeto de función que genera nuevos UUID utilizando recursos del sistema operativo ( CoCreateGuid en Windows, uuid_generate en Linux, CFUUIDCreate en Mac)Nota : Esto no es parte de la propuesta estándar. Está disponible solo si se define la macro UUID_SYSTEM_GENERATOR . |
uuid_time_generator | Un objeto de función experimental que genera UUID basados en el tiempo. Nota : Esta es una característica experimental y no debe usarse en ningún código de producción. Está disponible solo si se define la macro UUID_TIME_GENERATOR . |
Utilidades:
| Nombre | Descripción |
|---|---|
std::swap<> | Especialización de swap para uuid |
std::hash<> | Especialización del hash para uuid (necesario para almacenar UUID en contenedores asociativos desordenados, como std::unordered_set ) |
Constantes:
| Nombre | Descripción |
|---|---|
uuid_namespace_dns | ID de espacio de nombres para UUID basados en nombres cuando la cadena de nombre es un nombre de dominio totalmente calificado. |
uuid_namespace_url | ID de espacio de nombres para UUID basados en nombres cuando la cadena de nombre es una URL. |
uuid_namespace_oid | ID de espacio de nombres para UUID basados en nombres cuando Mame String es un ISO OID (ver https://oidref.com/, https://en.wikipedia.org/wiki/object_identifier). |
uuid_namespace_x500 | ID de espacio de nombres para UUID basados en nombres cuando la cadena de nombres es un X.500 DN, en DER o un formato de salida de texto (consulte https://en.wikipedia.org/wiki/x.500, https://en.wikipedia.org/wiki/abstract_syntax_notation_one). |
Otro:
| Nombre | Descripción |
|---|---|
operator== y operator!= | para la comparación de uuids para la igualdad/desigualdad |
operator< | Para comparar si uno de los uuidas es menos que otro. Aunque esta operación no tiene mucho sentido lógico, es necesario para almacenar UUID en un set std ::. |
operator<< | Para escribir un UUID en un flujo de salida utilizando la representación textual canónica. |
to_string() | Crea una cadena con la representación textual canónica de un UUID. |
Esta biblioteca es una implementación de la propuesta P0959.
A medida que la propuesta evoluciona en función del comité estándar y los comentarios de la comunidad C ++, esta implementación de la biblioteca reflejará esos cambios.
Vea la historia de revisión de la propuesta de historia de los cambios.
La siguiente es una lista de ejemplos para usar la biblioteca:
Creando un nil uuid
uuid empty;
assert (empty.is_nil());Creando un nuevo 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);Creación de un nuevo UUID con un generador aleatorio predeterminado
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);Creación de un nuevo UUID con un generador aleatorio particular
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);Creando un nuevo UUID con el generador de nombres
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);Crear un uuid desde una cadena
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);Creando un uuid a partir de una secuencia de 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");Comparando uuids
uuid empty;
uuid id = uuids::uuid_system_generator{}();
assert (empty == empty);
assert (id == id);
assert (empty != id);Intercambio de uuids
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());Convertir a cadena
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");Usar con un contenedor asociativo ordenado
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());Usar en un contenedor asociativo desordenado
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 Uuids
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 genera UUID utilizando el basic_uuid_random_generator y STD :: Random_device para sembrar un generador, tenga en cuenta que esto podría no ser no determinista y realmente generar la misma secuencia de números:
std :: random_device se puede implementar en términos de un motor de número pseudo-aleatorio definido por implementación si una fuente no determinista (por ejemplo, un dispositivo de hardware) no está disponible para la implementación. En este caso, cada objeto std :: random_device puede generar la misma secuencia de números.
Esto podría ser un problema con Mingw. Consulte el error 85494 - La implementación de Random_device en MingW es inútil. Esto se solucionó en GCC 9.2.
Una alternativa portátil es usar la biblioteca Boost.random.
La biblioteca es compatible con todos los principales sistemas operativos: Windows, Linux y Mac OS.
Si usa la biblioteca en un proyecto construido con C ++ 20, puede usar std::span . Esto se usa de forma predeterminada, si el encabezado es compatible con su compilador. La verificación se realiza con la macro de prueba __cpp_lib_span.
De lo contrario, como cuando se construye con C ++ 17, std::span no está disponible. Sin embargo, la Biblioteca de soporte de Microsoft Guidelines (también conocida como GSL) se puede usar para su implementación span (desde la cual se definió la versión estándar). La biblioteca stduuid predeterminada utiliza esta implementación si std::span no está disponible.
Para asegurarse de que se pueda usar gsl::span , asegúrese de que la biblioteca GSL esté disponible y que el directorio GSL incluye se enumere en los directorios de inclusión para el proyecto.
Si usa CMake para construir el proyecto de prueba, asegúrese de que la variable llamada UUID_USING_CXX20_SPAN no esté definida, o su valor está OFF (este es el valor predeterminado). Esto asegurará que el directorio gsl se incluirá en la lista de búsqueda de directorios de encabezados.
Un proyecto de prueba está disponible en las fuentes. Para construir y ejecutar las pruebas, haga lo siguiente:
build en el directorio raíz de las fuentescmake .. desde el directorio build ; Si no tiene CMake, primero debe instalarlo.Ejemplos
Para generar archivos de proyecto para Visual Studio 2019, puede ejecutar los siguientes comandos:
cd build
cmake -G "Visual Studio 17" -A x64 ..
Para habilitar el generador UUID del sistema operativo, establezca la variable UUID_SYSTEM_GENERATOR en ON .
cd build
cmake -G "Visual Studio 17" -A x64 -DUUID_SYSTEM_GENERATOR=ON ..
Para habilitar el generador UUID basado en el tiempo experimental, ON la variable UUID_TIME_GENERATOR .
cd build
cmake -G "Visual Studio 17" -A x64 -DUUID_TIME_GENERATOR=ON ..
La implementación SHA1 se basa en la biblioteca TinySha1.