diff --git a/std/typecons.d b/std/typecons.d index 3c425c7d7de..4f4e58c6a8d 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -3543,6 +3543,35 @@ struct Nullable(T) format!"%s"(a); } + /** + * Returns true if `this` has a value, otherwise false. + * + * Allows a `Nullable` to be used as the condition in an `if` statement: + * + * --- + * if (auto result = functionReturningNullable()) + * { + * doSomethingWith(result.get); + * } + * --- + */ + bool opCast(T : bool)() const + { + return !isNull; + } + + /// Prevents `opCast` from disabling built-in conversions. + auto ref T opCast(T, this This)() + if (is(This : T) || This.sizeof == T.sizeof) + { + static if (is(This : T)) + // Convert implicitly + return this; + else + // Reinterpret + return *cast(T*) &this; + } + /** * Forces `this` to the null state. */ @@ -4400,6 +4429,26 @@ auto nullable(T)(T t) assert(destroyed); } +// https://issues.dlang.org/show_bug.cgi?id=22293 +@safe unittest +{ + Nullable!int empty; + Nullable!int full = 123; + + assert(cast(bool) empty == false); + assert(cast(bool) full == true); + + if (empty) assert(0); + if (!full) assert(0); +} + +// check that opCast doesn't break unsafe casts +@system unittest +{ + Nullable!(const(int*)) a; + auto result = cast(immutable(Nullable!(int*))) a; +} + /** Just like `Nullable!T`, except that the null state is defined as a particular value. For example, $(D Nullable!(uint, uint.max)) is an