Uma implementação da biblioteca de cabeça única C ++ 17 de plataforma cruzada para identificadores universalmente exclusivos , basta conhecer como UUID ou GUID (principalmente no Windows). Um UUID é um número de 128 bits usado para identificar exclusivamente informações em sistemas de computador, como teclas de tabela de banco de dados, interfaces com, classes e bibliotecas de tipos e muitas outras.
Para obter informações sobre UUID/GUIDS, consulte:
Embora a especificação coloque a biblioteca UUID no espaço para nome de std , essa implementação usa o espaço para o nome uuids para esse fim, a fim de tornar a biblioteca utilizável sem violar as restrições impostas ao espaço para nome std . Os seguintes tipos e utilitários estão disponíveis:
Tipos básicos:
| Nome | Descrição |
|---|---|
uuid | uma classe representando um UUID; Isso pode ser construído padrão (um nulo), construído a partir de um intervalo (definido por um par de iteradores) ou a partir de um span . |
uuid_variant | um enume |
uuid_version | um enume |
Geradores:
| Nome | Descrição |
|---|---|
basic_uuid_random_generator | Um objeto de função que gera a versão 4 UUIDS usando um motor gerador de números pseudo-aleatórios. |
uuid_random_generator | Um basic_uuid_random_generator usando o mecanismo Mersenne Twister ( basic_uuid_random_generator<std::mt19937> ) |
uuid_name_generator | Um objeto de função que gera a versão 5, uuids baseados em nome usando o hash sha1. |
uuid_system_generator | Um objeto de função que gera novos UUIDs usando os recursos do sistema operacional ( CoCreateGuid no Windows, uuid_generate no Linux, CFUUIDCreate no Mac)Nota : Isso não faz parte da proposta padrão. Está disponível apenas se a macro UUID_SYSTEM_GENERATOR estiver definida. |
uuid_time_generator | um objeto de função experimental que gera UUIDs baseados no tempo. Nota : Este é um recurso experimental e não deve ser usado em nenhum código de produção. Está disponível apenas se a macro UUID_TIME_GENERATOR estiver definida. |
Utilitários:
| Nome | Descrição |
|---|---|
std::swap<> | Especialização da swap para uuid |
std::hash<> | Especialização do hash para uuid (necessário para armazenar UUIDs em contêineres associativos não ordenados, como std::unordered_set ) |
Constantes:
| Nome | Descrição |
|---|---|
uuid_namespace_dns | Namespace ID para uuids baseados em nome quando o nome String é um nome de domínio totalmente qualificado. |
uuid_namespace_url | Namespace ID para uuids baseados em nome quando o nome String é um URL. |
uuid_namespace_oid | Namespace ID para UUIDS baseado em nome quando a String Mame é um ISO OID (consulte https://oidref.com/, https://en.wikipedia.org/wiki/object_identifier). |
uuid_namespace_x500 | Namespace ID para UUIDS baseado em nome quando o nome String é um X.500 DN, em DER ou um formato de saída de texto (consulte https://en.wikipedia.org/wiki/X.500, https://en.wikipedia.org/wiki/abstract_syntps://enone). |
Outro:
| Nome | Descrição |
|---|---|
operator== e operator!= | Para comparação de UUIDs para igualdade/desigualdade |
operator< | Para comparar se um UUIDS é menor que outro. Embora esta operação não faça muito sentido lógico, é necessário para armazenar UUIDs em um conjunto de std ::. |
operator<< | Para escrever um UUID em um fluxo de saída usando a representação textual canônica. |
to_string() | Cria uma string com a representação textual canônica de um UUID. |
Esta biblioteca é uma implementação da proposta P0959.
À medida que a proposta evolui com base no comitê padrão e no feedback da comunidade C ++, essa implementação da biblioteca refletirá essas mudanças.
Veja o histórico de revisão da proposta de histórico de mudanças.
A seguir, é apresentada uma lista de exemplos para o uso da biblioteca:
Criando um nulo uuid
uuid empty;
assert (empty.is_nil());Criando um novo 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);Criando um novo Uuid com um gerador aleatório padrão
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);Criando um novo Uuid com um determinado gerador aleatório
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);Criando um novo Uuid com o gerador de nomes
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);Crie um Uuid a partir de uma string
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);Criando um Uuid a partir de uma sequência 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);Trocando os 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());Convertendo em 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");Usando com um contêiner associativo 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());Usando em um contêiner associativo não 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::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)); Se você gerar UUIDs usando o basic_uuid_random_generator e STD :: Random_Device para semear um gerador, lembre-se de que isso pode não ser não determinístico e realmente gerar a mesma sequência de números:
STD :: Random_Device pode ser implementado em termos de um mecanismo de número pseudo-aleatom definido por implementação se uma fonte não determinística (por exemplo, um dispositivo de hardware) não estiver disponível para a implementação. Nesse caso, cada objeto STD :: Random_Device pode gerar a mesma sequência de números.
Isso pode ser um problema com Mingw. Consulte Bug 85494 - A implementação do Random_Device no Mingw é inútil. Isso foi corrigido no GCC 9.2.
Uma alternativa portátil é usar a biblioteca Boost.Random.
A biblioteca é suportada em todos os principais sistemas operacionais: Windows, Linux e Mac OS.
Se você usar a biblioteca em um projeto construído com C ++ 20, poderá usar std::span . Isso é usado por padrão, se o cabeçalho for suportado pelo seu compilador. A verificação é feita com a macro __CPP_LIB_SPAN Test-Test.
Caso contrário, como ao construir com C ++ 17, std::span não está disponível. No entanto, a Biblioteca de Suporte das Diretrizes da Microsoft (também conhecida como GSL) pode ser usada para sua implementação span (a partir da qual a versão padrão foi definida). A biblioteca STDUUID é padronizada para usar essa implementação se std::span não estiver disponível.
Para garantir que gsl::span possa ser usado, verifique se a biblioteca GSL está disponível e o diretório GSL inclui os diretórios de inclusão do projeto.
Se você usar o CMake para criar o projeto de teste, verifique se a variável chamada UUID_USING_CXX20_SPAN não está definida ou o valor está OFF (este é o valor padrão). Isso garantirá que o diretório gsl será incluído na lista de pesquisa de diretórios de cabeçalho.
Um projeto de teste está disponível nas fontes. Para construir e executar os testes, faça o seguinte:
build no diretório raiz das fontescmake .. no diretório build ; Se você não tiver cmake, deve instalá -lo primeiro.Exemplos
Para gerar arquivos de projeto para o Visual Studio 2019, você pode executar os seguintes comandos:
cd build
cmake -G "Visual Studio 17" -A x64 ..
Para ativar o sistema operacional UUID Generator Defina a variável UUID_SYSTEM_GENERATOR para ON .
cd build
cmake -G "Visual Studio 17" -A x64 -DUUID_SYSTEM_GENERATOR=ON ..
Para ativar o gerador UUID baseado em tempo experimental, defina a variável UUID_TIME_GENERATOR para ON .
cd build
cmake -G "Visual Studio 17" -A x64 -DUUID_TIME_GENERATOR=ON ..
A implementação SHA1 é baseada na biblioteca Tinysha1.