stduuid – A C++ library for universally unique identifiers

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);   
  • Creating a UUID from an array

    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");
  • Comparing UUIDS

    uuid empty;
    uuid guid = uuids::uuid_system_generator{}();
    
    assert(empty == empty);
    assert(guid == guid);
    assert(empty != guid);
  • Swapping UUIDS

    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());
  • Converting to string

    uuid empty;
    assert(uuids::to_string(empty) == "00000000-0000-0000-0000-000000000000");
    assert(uuids::to_wstring(empty) == L"00000000-0000-0000-0000-000000000000");
  • Iterating through the UUID data

    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);
  • Using with an orderered associative container

    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());
  • Using in an unordered associative container

    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());
  • Hashing UUIDs

    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.

4 Replies to “stduuid – A C++ library for universally unique identifiers”

  1. Interesant, felicitari și pt prezentarea de ieri, a fost mișto, păcat că nu ai stat și la party 🙂

  2. This looks like it will be quite handy. Any plans to make this available via vcpkg?

  3. 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?

  4. 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?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.