I have recently submitted a proposal for a new standard library for universally unique identifiers. The library is called uuid and the paper, P0959R0 – A Proposal for a Universally Unique Identifier Library, is available on Github. The design of the library is inspired by the Boost Uuid Library and the Crossuuid library. I got lots of great feedback that shaped the formed of the proposal from people on the ISO C++ Standard – Future Proposals forum.
I have made an implementation of the library, which is called stduuid, and again, it available on github. This implementation is supported on all major operating systems: Windows, Linux and Mac OS.
Motivation
Universally unique identifiers (uuid), also known as Globally Unique Identifiers (guids), are commonly used in many types of applications to uniquely identify data. A standard uuid library would benefit developers that currently have to either use operating system specific APIs for creating new uuids or resort to 3rd party libraries, such as boost::uuid.
UUIDs are 128-bit numbers that are for most practical purposes unique, without depending on a central registration authority for ensuring their uniqueness. Although the probability of UUID duplication exists, it is negligible. According to Wikipedia, “for there to be a one in a billion chance of duplication, 103 trillion version 4 UUIDs must be generated.” UUID is an Internet Engineering Task Force standard described by RFC 4122.
The library proposed on this paper is a light one: it enables developers to generate random and name-based UUIDs, serialize and deserialize UUIDs to and from strings, validate UUIDs and other common operations.
Using the library
The following is a list of examples for using the library:
-
Creating a nil UUID
uuid empty; assert(empty.nil()); assert(empty.size() == 16);
-
Creating a new UUID
uuid const guid = uuids::uuid_system_generator{}(); assert(!guid.nil()); assert(guid.size() == 16); assert(guid.version() == uuids::uuid_version::random_number_based); assert(guid.variant() == uuids::uuid_variant::rfc);
-
Creating a new UUID with a default random generator
uuids::uuid_random_generator gen; uuid const guid = gen(); assert(!guid.nil()); assert(guid.size() == 16); assert(guid.version() == uuids::uuid_version::random_number_based); assert(guid.variant() == uuids::uuid_variant::rfc);
-
Creating a new UUID with a particular random generator
std::random_device rd; std::ranlux48_base generator(rd()); uuids::basic_uuid_random_generator<std::ranlux48_base> gen(&generator); uuid const guid = gen(); assert(!guid.nil()); assert(guid.size() == 16); assert(guid.version() == uuids::uuid_version::random_number_based); assert(guid.variant() == uuids::uuid_variant::rfc);
-
Creating a new UUID with the name generator
uuids::uuid_name_generator gen; uuid const guid = gen(); assert(!guid.nil()); assert(guid.size() == 16); assert(guid.version() == uuids::uuid_version::name_based_sha1); assert(guid.variant() == uuids::uuid_variant::rfc);
Create a UUID from a string
using namespace std::string_literals; auto str = "47183823-2574-4bfd-b411-99ed177d3e43"s; uuid guid(str); assert(guid.string() == str);
or
auto str = L"47183823-2574-4bfd-b411-99ed177d3e43"s; uuid guid(str); assert(guid.wstring() == str);
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 guid(std::begin(arr), std::end(arr)); assert(id.string() == "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 guid(std::begin(arr), std::end(arr)); assert(guid.string() == "47183823-2574-4bfd-b411-99ed177d3e43");
uuid empty; uuid guid = uuids::uuid_system_generator{}(); assert(empty == empty); assert(guid == guid); assert(empty != guid);
uuid empty; uuid guid = uuids::uuid_system_generator{}(); assert(empty.nil()); assert(!guid.nil()); std::swap(empty, guid); assert(!empty.nil()); assert(guid.nil()); empty.swap(guid); assert(empty.nil()); assert(!guid.nil());
uuid empty; assert(uuids::to_string(empty) == "00000000-0000-0000-0000-000000000000"); assert(uuids::to_wstring(empty) == L"00000000-0000-0000-0000-000000000000");
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 guid; assert(guid.nil()); std::copy(std::cbegin(arr), std::cend(arr), std::begin(guid)); assert(!guid.nil()); assert(guid.string() == "47183823-2574-4bfd-b411-99ed177d3e43"); size_t i = 0; for (auto const & b : guid) assert(arr[i++] == b);
uuids::uuid_random_generator gen; std::set<uuids::uuid> ids{uuid{}, gen(), gen(), gen(), gen()}; assert(ids.size() == 5); assert(ids.find(uuid{}) != ids.end());
uuids::uuid_random_generator gen; std::unordered_set<uuids::uuid> ids{uuid{}, gen(), gen(), gen(), gen()}; assert(ids.size() == 5); assert(ids.find(uuid{}) != ids.end());
auto h1 = std::hash<std::string>{}; auto h2 = std::hash<uuid>{}; assert(h1(str) == h2(guid));
You can read more about the library, including the proposed paper, on Github. I encourage you to try the library and provide feedback, whether here or on github, on the issues or the suggestions that you might have.
Interesant, felicitari și pt prezentarea de ieri, a fost mișto, păcat că nu ai stat și la party 🙂
This looks like it will be quite handy. Any plans to make this available via vcpkg?
I am a bit slow on this. I am migrating my Visual C++ code so it only uses standard template library and such things and not Microsoft or even COM specific calls. Currently my unique ID generator looks like this:
CString GP_Pop::GUIDgen()
{
GUID guid;
CoCreateGuid(&guid);
BYTE * str;
UuidToString((UUID*)&guid, &str);
CString unique ((LPTSTR) str);
RpcStringFree(&str);
unique.Replace(_T(“-“), _T(“_”));
return unique;
}
What do you suggest I replace this with. Could you give me a more step by step. I have not used GitHub too much and where do I bring your library and link it?
This library looks great. I am pleased it is based on the boost one, which I have used to great effect in the past. I wonder why there seems to be little interest. The last time I used uuids I used them in a messaging system where they are good for the unique message ids and correlation ids in request-reply systems. How are things going with ISO/WG21 and standardization?