UdonLibrary 1.0.0
機械システム研究部 C++ ライブラリ
読み取り中…
検索中…
一致する文字列を見つけられません
Optional 型

Optional 型は有効な値を持つか、もしくは無効な値かを表す型です。

std::optional 型と同義ですが、C++17 からでしか使えないため Udon:Optional 型を実装しています。大まか次のように実装されています。テンプレート引数に渡された型のオブジェクト(値)を持ちます。

template <typename T>
class Optional
{
T value; // 値
bool hasValue; // true: 有効値 false: 無効値
};

次のように戻り値にエラー情報を付与したい場合に用います。

Udon::Optional<int> division(int l, int r)
{
if (r == 0)
return Udon::nullopt; // 無効値
else
return l / r; // 有効値
}
オプショナル型
Definition Optional.hpp:62
constexpr NulloptT nullopt
無効値
Definition Optional.hpp:52

個別インクルード

有/無効値の判定

if (const Udon::Optional<int> result = division(100, 0))
{
// 有効値
}
else
{
// 無効値
}

有効値かどうかは hasValue() operator bool メンバ関数によって取得できます。

const Udon::Optional<int> result = division(100, 0);
bool hasValue = result.hasValue(); // hasValue == false
bool hasValue = static_cast<bool>(result); // hasValue == false
constexpr bool hasValue() const noexcept
値が有効か
Definition Optional.hpp:308

if 文の判定式にオブジェクトを渡すと、bool 型への明示的なキャストとしてコンパイルされ、operator bool が呼び出されます。

const Udon::Optional<int> result = division(100, 0);
if (result)
{
// 有効値
}
else
{
// 無効値
}

一般的には最初の例のように書きます。変数のスコープを if 文に閉じ込められるので、よりスマートです。

値の参照

値は operator * value() によって参照できます。

無効値の場合、値の取得はしてはならず、未定義動作となります。例外の送出できる環境では、例外オブジェクト Udon::BadOptionalAccess がスローされます。

if (const Udon::Optional<int> result = division(100, 10))
{
int value = result.value(); // value == 10
}
ValueType & value() &
値を取得
Definition Optional.hpp:319

Optional::operator * はポインタでの * を模倣して定義されています。ポインタでの * 演算子はポインタ先の参照を返すのに対し、Optional::operator * が持つ値オブジェクトへの参照を返します。

if (const Udon::Optional<int> result = division(100, 10))
{
int value = *result; // value == 10
}

Optional が 構造体オブジェクトを持つ場合は operator-> によって構造体のメンバを直接参照できます。こちらもポインタのアロー演算子の模倣です。

struct Vec2
{
double x;
double y;
};
Udon::Optional<Vec2> divisionVector(const Vec2& l, double r)
{
if (r == 0)
return Udon::nullopt;
else
return { l.x / r, r.y / r };
}
// ... 略
if (const Udon::Optional<Vec2> result = divisionVector({ 100, 200 }, 5))
{
double x = result->x;
}

有効値のセット

通常の変数と同じように扱えます。

初期化時にセット

Udon::Optional<int> value = 100;
if (value)
{
// exec this statement
}

代入時にセット

value = 100;
if (value)
{
// exec this statement
}

無効値のセット

Udon::nullopt オブジェクトを初期化、代入時にセットすると無効値となります。

if (nullOptional)
{
}
else
{
// exec this statement
}

また初期値を渡さずインスタンス化した際も無効値となります。

Udon::Optional<int> nullOptional;

既に有効値を持つ場合、reset メンバ関数で無効値にできます。

Udon::Optional<int> value = 100;
value.reset();
if (nullOptional)
{
}
else
{
// exec this statement
}
void reset() noexcept(std::is_nothrow_destructible< ValueType >::value)
無効状態にする (トリビアルな型)
Definition Optional.hpp:491

本ライブラリでの使われ方

本ライブラリでは Optional 型を通信受信時のエラーチェックに用いています。

受信用クラスには受信したオブジェクトを返す getMessage() メンバ関数がありますが、この関数は受信した T 型オブジェクトを Optional<T> で返します。

受信エラーの際は無効値を返すため、エラー処理を次のように書けます。

ReaderClass<Udon::Message::Motor> reader;
void loop()
{
if (const Udon::Optional<Udon::Message::Motor> message = reader.getMessage())
{
motor.move(message->power);
}
else
{
// receive failed
}
}

auto 型で受け取ると短く書けます。

if (const auto message = reader.getMessage())
{
motor.move(message->power);
}
else
{
// receive failed
}