LoginSignup
0
1

C++のboostライブラリによるUUID

Last updated at Posted at 2024-02-23

はじめに

 本記事はboostライブラリを使用したC++でUUIDを使用する方法を説明します。

環境

・2024/02/23
・GitHub Codespaces

UUIDとは

 UUID(Universally Unique IDentifiler)は36文字(128bit)の英数字で情報を識別するために使用される文字列のことです。生成規則から生成されたUUIDは、他に生成されたUUIDと同一となる可能性は非常に低いです。そのためUUIDは一意の情報としての価値が高く、データベースなどのユニークIDとして使用されます。

UUIDの例:c2253419-a003-4431-95cf-fe8db55938ac

C++のUUID

 C++は標準データ型としてuuid_tを持ちますが、非常に機能が弱いです。そこで本記事はboostライブラリに含まれるUUIDの使用法を説明します。
 boostライブラリのインストール方法は以下の記事を参考にしてください。

使い方

 以下はboostライブラリがインストールされていることを前提に説明します。
 幾つかのコード例を提示しますが、コードを実際の実行環境で確認したい場合は以下のコマンドでコンパイルしてください。boostのビルドが/usr/localで成されていることを前提としているため、boostのライブラリとヘッダーが/usr/local/libと/usr/local/includeに存在しない場合、都度コンパイルコマンドに変更を加えてください。

g++ -o example example.cpp -I /usr/local/include/boost -L /usr/local/lib

UUID生成

 UUIDはrandom_generatorで生成する。

generate.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

int main()
{
    // UUIDを生成する
    boost::uuids::uuid uuid = boost::uuids::random_generator()();
    // UUIDを文字列に変換して表示する
    std::cout << uuid << std::endl;
    return 0;
}

UUID➡文字列変換

 uuid型はlexical_castで文字列型を変換する。

conversion1.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/lexical_cast.hpp>

int main()
{
    // UUIDを生成する
    boost::uuids::uuid uuid = boost::uuids::random_generator()();
    // UUIDを文字列に変換
    std::string s = boost::lexical_cast<std::string>(uuid);
    // 文字列を表示する
    std::cout << s << std::endl;
    return 0;
}

文字列➡UUID

 文字列型はlexical_castでUUID型に変換する。

conversion2.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/lexical_cast.hpp>

int main()
{
   std::string s = "c2253419-a003-4431-95cf-fe8db55938ac";
   // 文字列をUUIDに変換
   boost::uuids::uuid uuid = boost::lexical_cast<boost::uuids::uuid>(s);
   // UUIDを文字列に変換して表示する
   std::cout << uuid << std::endl;
   return 0;
}

UUIDのコピー

 UUIDは代入することでコピーが行える。

copy.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

int main()
{
   // UUIDを生成する
   boost::uuids::uuid uuid1 = boost::uuids::random_generator()();
   // UUIDをコピーする
   boost::uuids::uuid uuid2 = uuid1;
   // UUIDを文字列に変換して表示する
   std::cout << uuid2 << std::endl;
   return 0;
}

UUIDの比較

 UUIDは等価演算子により比較を行うことができる。

comparison.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

int main()
{
    // UUIDを生成する
    boost::uuids::uuid uuid1 = boost::uuids::random_generator()();
    boost::uuids::uuid uuid2 = boost::uuids::random_generator()();
    // UUIDをコピーする
    boost::uuids::uuid uuid3 = uuid1;
    // UUIDを比較
    bool b1 =uuid1 == uuid2;
    bool b2 =uuid1 == uuid3;
    // UUIDを文字列に変換して表示する
    std::cout << "b1:" << b1 << std::endl;
    std::cout << "b2:" << b2 << std::endl;
    return 0;
}

実行した場合以下のような結果を得る。

b1:0
b2:1

nil値の生成

 nil値とは値が存在しないことを示す特別な情報のことです。
 nilはnil_generatorで生成する。

nil.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

int main()
{
   // nil値を生成する
   boost::uuids::uuid nil = boost::uuids::nil_generator{}();
   // nil値を表示する
   std::cout << nil << std::endl;
   return 0;
}

実行した場合以下のような結果を得る。

00000000-0000-0000-0000-000000000000

nil値の判別

UUIDがnil値であるかis_nilで判別することができる。

decision.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

int main()
{
    // UUIDを生成する
    boost::uuids::uuid uuid = boost::uuids::random_generator()();
    // nil値を生成する
    boost::uuids::uuid nil = boost::uuids::nil_generator{}();
    // nilか判別する
    bool b1 = uuid.is_nil();
    bool b2 = nil.is_nil();
    // 結果を表示する
    std::cout << "b1:" << b1 << std::endl;
    std::cout << "b2:" << b2 << std::endl;
    return 0;
}

実行した場合以下のような結果を得る。

b1:0
b2:1

ハッシュマップ作製:int

 boostにあるUUIDの最大の特徴はハッシュマップ作製の機能が標準で搭載されている点です。UUIDからハッシュマップを作成することが可能となります。例としてint型のデータを探索するハッシュマップを作成しましょう。
 ハッシュマップはunoredered_mapで生成できます。テンプレートパラメータにデータ型を指定し、そのデータを格納します。以下の例では、boost::uuids::uuidとintでハッシュマップのキーとデータの型を決定しています。
 

hashmap1.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/unordered_map.hpp>

int main()
{
   // UUIDを生成する
   boost::uuids::uuid uuid1 = boost::uuids::random_generator()();
   boost::uuids::uuid uuid2 = boost::uuids::random_generator()();
   // ハッシュマップ作製
   boost::unordered_map<boost::uuids::uuid, int> map;
   map[uuid1] = 100;
   map[uuid2] = 200;
   // ハッシュマップから数字を表示する
   std::cout << "map[uuid1] :" << map[uuid1] << std::endl;
   std::cout << "map[uuid2] :" << map[uuid2] << std::endl;
   return 0;
}

実行した場合以下のような結果を得る。

map[uuid1] :100
map[uuid2] :200

ハッシュマップ作製:string

 前例はint型のデータを格納しました。ならば、他の型を格納することも当然出来るだろうということで、検証しましょう。以下の例では、boost::uuids::uuidとstringでハッシュマップのキーとデータの型を決定しています。

hashmap2.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/unordered_map.hpp>

int main()
{
    // UUIDを生成する
    boost::uuids::uuid uuid1 = boost::uuids::random_generator()();
    boost::uuids::uuid uuid2 = boost::uuids::random_generator()();
    // ハッシュマップ作製
    boost::unordered_map<boost::uuids::uuid, std::string> map;
    map[uuid1] = "one hundred";
    map[uuid2] = "two hundred";
    // ハッシュマップから数字を表示する
    std::cout << "map[uuid1] :" << map[uuid1] << std::endl;
    std::cout << "map[uuid2] :" << map[uuid2] << std::endl;
    return 0;
}

実行した場合以下のような結果を得る。

map[1] :one hundred
map[2] :two hundred

ハッシュマップの応用

 ハッシュマップはテンプレートパラメータを自由に設定できるため、自身で定義した構造体なども入れられます。int型などでは、UUID一つに対しデータが一つに限られますが、構造体を自身で定義すれば、複数のデータをハッシュマップと結びつけられます。以下がハッシュマップの応用例です。

hashmap3.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/unordered_map.hpp>

struct Student {
   std::string name;
   int age;
};

int main()
{
   // UUIDを生成する
   boost::uuids::uuid uuid1 = boost::uuids::random_generator()();
   boost::uuids::uuid uuid2 = boost::uuids::random_generator()();
   // ハッシュマップ作製
   boost::unordered_map<boost::uuids::uuid, Student*> map;
   Student *s1 = new Student;
   s1->name = "Alice";
   s1->age = 20;
   Student *s2 = new Student;
   s2->name = "Clara";
   s2->age = 105;
   map[uuid1] = s1;
   map[uuid2] = s2;
   // ハッシュマップから数字を表示する
   std::cout << "map[uuid1]->name :" << map[uuid1]->name << std::endl;
   std::cout << "map[uuid2]->name :" << map[uuid2]->name << std::endl;
   return 0;
}

 実行した場合以下のような結果を得る。

map[uuid1]->name :Alice
map[uuid2]->name :Clara

蛇足

 本記事で紹介してハッシュマップ作製では、unordered_mapのテンプレートパラメータの第一パラメータをUUIDで固定しました。しかし、テンプレートパラメータの第一項が指定できるのであれば、UUID以外も使用できるのではないだろうかと気になり検証した。

extraordinary.cpp
#include <iostream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/unordered_map.hpp>

int main()
{
   // ハッシュマップ作製
   boost::unordered_map<int, std::string> map;
   map[1] = "one hundred";
   map[2] = "two hundred";
   // ハッシュマップから数字を表示する
   std::cout << "map[1] :" << map[1] << std::endl;
   std::cout << "map[2] :" << map[2] << std::endl;
   return 0;
}

 実行した場合以下のような結果を得る。

map[1] :one hundred
map[2] :two hundred

ps. 私はまだC++に関して初心者なのですが、C++にはどうやらmapという、上記で示したハッシュマップと似たものが標準で搭載されているのですね。ChatGPT君に聞いてみれば以下の様な違いがあると教えてくれました。

image.png

参考記事

0
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1