mirror of
https://github.com/dlang/phobos.git
synced 2025-05-05 09:30:49 +03:00
Merge pull request #3114 from MetaLang/nullable-doc-fixes
Improve Nullable documentation
This commit is contained in:
commit
ddfd111ab5
1 changed files with 205 additions and 10 deletions
215
std/typecons.d
215
std/typecons.d
|
@ -1764,6 +1764,9 @@ struct Nullable(T)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Constructor initializing $(D this) with $(D value).
|
Constructor initializing $(D this) with $(D value).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
value = The value to initialize this `Nullable` with.
|
||||||
*/
|
*/
|
||||||
this(inout T value) inout
|
this(inout T value) inout
|
||||||
{
|
{
|
||||||
|
@ -1789,13 +1792,26 @@ Constructor initializing $(D this) with $(D value).
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns $(D true) if and only if $(D this) is in the null state.
|
Check if `this` is in the null state.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
true $(B iff) `this` is in the null state, otherwise false.
|
||||||
*/
|
*/
|
||||||
@property bool isNull() const @safe pure nothrow
|
@property bool isNull() const @safe pure nothrow
|
||||||
{
|
{
|
||||||
return _isNull;
|
return _isNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
Nullable!int ni;
|
||||||
|
assert(ni.isNull);
|
||||||
|
|
||||||
|
ni = 0;
|
||||||
|
assert(!ni.isNull);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Forces $(D this) to the null state.
|
Forces $(D this) to the null state.
|
||||||
*/
|
*/
|
||||||
|
@ -1805,9 +1821,22 @@ Forces $(D this) to the null state.
|
||||||
_isNull = true;
|
_isNull = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
Nullable!int ni = 0;
|
||||||
|
assert(!ni.isNull);
|
||||||
|
|
||||||
|
ni.nullify();
|
||||||
|
assert(ni.isNull);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Assigns $(D value) to the internally-held state. If the assignment
|
Assigns $(D value) to the internally-held state. If the assignment
|
||||||
succeeds, $(D this) becomes non-null.
|
succeeds, $(D this) becomes non-null.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
value = A value of type `T` to assign to this `Nullable`.
|
||||||
*/
|
*/
|
||||||
void opAssign()(T value)
|
void opAssign()(T value)
|
||||||
{
|
{
|
||||||
|
@ -1815,9 +1844,32 @@ succeeds, $(D this) becomes non-null.
|
||||||
_isNull = false;
|
_isNull = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
If this `Nullable` wraps a type that already has a null value
|
||||||
|
(such as a pointer), then assigning the null value to this
|
||||||
|
`Nullable` is no different than assigning any other value of
|
||||||
|
type `T`, and the resulting code will look very strange. It
|
||||||
|
is strongly recommended that this be avoided by instead using
|
||||||
|
the version of `Nullable` that takes an additional `nullValue`
|
||||||
|
template argument.
|
||||||
|
*/
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
//Passes
|
||||||
|
Nullable!(int*) npi;
|
||||||
|
assert(npi.isNull);
|
||||||
|
|
||||||
|
//Passes?!
|
||||||
|
npi = null;
|
||||||
|
assert(!npi.isNull);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Gets the value. $(D this) must not be in the null state.
|
Gets the value. $(D this) must not be in the null state.
|
||||||
This function is also called for the implicit conversion to $(D T).
|
This function is also called for the implicit conversion to $(D T).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The value held internally by this `Nullable`.
|
||||||
*/
|
*/
|
||||||
@property ref inout(T) get() inout @safe pure nothrow
|
@property ref inout(T) get() inout @safe pure nothrow
|
||||||
{
|
{
|
||||||
|
@ -1826,6 +1878,20 @@ This function is also called for the implicit conversion to $(D T).
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
import std.exception: assertThrown, assertNotThrown;
|
||||||
|
|
||||||
|
Nullable!int ni;
|
||||||
|
//`get` is implicitly called. Will throw
|
||||||
|
//an AssertError in non-release mode
|
||||||
|
assertThrown!Throwable(ni == 0);
|
||||||
|
|
||||||
|
ni = 0;
|
||||||
|
assertNotThrown!Throwable(ni == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Implicitly converts to $(D T).
|
Implicitly converts to $(D T).
|
||||||
$(D this) must not be in the null state.
|
$(D this) must not be in the null state.
|
||||||
|
@ -1836,11 +1902,33 @@ $(D this) must not be in the null state.
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
Nullable!int a;
|
struct CustomerRecord
|
||||||
assert(a.isNull);
|
{
|
||||||
a = 5;
|
string name;
|
||||||
assert(!a.isNull);
|
string address;
|
||||||
assert(a == 5);
|
int customerNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nullable!CustomerRecord getByName(string name)
|
||||||
|
{
|
||||||
|
//A bunch of hairy stuff
|
||||||
|
|
||||||
|
return Nullable!CustomerRecord.init;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto queryResult = getByName("Doe, John");
|
||||||
|
if (!queryResult.isNull)
|
||||||
|
{
|
||||||
|
//Process Mr. Doe's customer record
|
||||||
|
auto address = queryResult.address;
|
||||||
|
auto customerNum = queryResult.customerNum;
|
||||||
|
|
||||||
|
//Do some things with this customer's info
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Add the customer to the database
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
|
@ -2121,6 +2209,12 @@ particular value. For example, $(D Nullable!(uint, uint.max)) is an
|
||||||
$(D uint) that sets aside the value $(D uint.max) to denote a null
|
$(D uint) that sets aside the value $(D uint.max) to denote a null
|
||||||
state. $(D Nullable!(T, nullValue)) is more storage-efficient than $(D
|
state. $(D Nullable!(T, nullValue)) is more storage-efficient than $(D
|
||||||
Nullable!T) because it does not need to store an extra $(D bool).
|
Nullable!T) because it does not need to store an extra $(D bool).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
T = The wrapped type for which Nullable provides a null value.
|
||||||
|
|
||||||
|
nullValue = The null value which denotes the null state of this
|
||||||
|
`Nullable`. Must be of type `T`.
|
||||||
*/
|
*/
|
||||||
struct Nullable(T, T nullValue)
|
struct Nullable(T, T nullValue)
|
||||||
{
|
{
|
||||||
|
@ -2128,6 +2222,9 @@ struct Nullable(T, T nullValue)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Constructor initializing $(D this) with $(D value).
|
Constructor initializing $(D this) with $(D value).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
value = The value to initialize this `Nullable` with.
|
||||||
*/
|
*/
|
||||||
this(T value)
|
this(T value)
|
||||||
{
|
{
|
||||||
|
@ -2152,7 +2249,10 @@ Constructor initializing $(D this) with $(D value).
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns $(D true) if and only if $(D this) is in the null state.
|
Check if `this` is in the null state.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
true $(B iff) `this` is in the null state, otherwise false.
|
||||||
*/
|
*/
|
||||||
@property bool isNull() const
|
@property bool isNull() const
|
||||||
{
|
{
|
||||||
|
@ -2168,6 +2268,17 @@ Returns $(D true) if and only if $(D this) is in the null state.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
Nullable!(int, -1) ni;
|
||||||
|
//Initialized to "null" state
|
||||||
|
assert(ni.isNull);
|
||||||
|
|
||||||
|
ni = 0;
|
||||||
|
assert(!ni.isNull);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Forces $(D this) to the null state.
|
Forces $(D this) to the null state.
|
||||||
*/
|
*/
|
||||||
|
@ -2176,18 +2287,58 @@ Forces $(D this) to the null state.
|
||||||
_value = nullValue;
|
_value = nullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
Nullable!(int, -1) ni = 0;
|
||||||
|
assert(!ni.isNull);
|
||||||
|
|
||||||
|
ni = -1;
|
||||||
|
assert(ni.isNull);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Assigns $(D value) to the internally-held state. No null checks are
|
Assigns $(D value) to the internally-held state. If the assignment
|
||||||
made. Note that the assignment may leave $(D this) in the null state.
|
succeeds, $(D this) becomes non-null. No null checks are made. Note
|
||||||
|
that the assignment may leave $(D this) in the null state.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
value = A value of type `T` to assign to this `Nullable`.
|
||||||
|
If it is `nullvalue`, then the internal state of
|
||||||
|
this `Nullable` will be set to null.
|
||||||
*/
|
*/
|
||||||
void opAssign()(T value)
|
void opAssign()(T value)
|
||||||
{
|
{
|
||||||
_value = value;
|
_value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
If this `Nullable` wraps a type that already has a null value
|
||||||
|
(such as a pointer), and that null value is not given for
|
||||||
|
`nullValue`, then assigning the null value to this `Nullable`
|
||||||
|
is no different than assigning any other value of type `T`,
|
||||||
|
and the resulting code will look very strange. It is strongly
|
||||||
|
recommended that this be avoided by using `T`'s "built in"
|
||||||
|
null value for `nullValue`.
|
||||||
|
*/
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
//Passes
|
||||||
|
enum nullVal = cast(int*)0xCAFEBABE;
|
||||||
|
Nullable!(int*, nullVal) npi;
|
||||||
|
assert(npi.isNull);
|
||||||
|
|
||||||
|
//Passes?!
|
||||||
|
npi = null;
|
||||||
|
assert(!npi.isNull);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Gets the value. $(D this) must not be in the null state.
|
Gets the value. $(D this) must not be in the null state.
|
||||||
This function is also called for the implicit conversion to $(D T).
|
This function is also called for the implicit conversion to $(D T).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The value held internally by this `Nullable`.
|
||||||
*/
|
*/
|
||||||
@property ref inout(T) get() inout
|
@property ref inout(T) get() inout
|
||||||
{
|
{
|
||||||
|
@ -2198,13 +2349,57 @@ This function is also called for the implicit conversion to $(D T).
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
import std.exception: assertThrown, assertNotThrown;
|
||||||
|
|
||||||
|
Nullable!(int, -1) ni;
|
||||||
|
//`get` is implicitly called. Will throw
|
||||||
|
//an error in non-release mode
|
||||||
|
assertThrown!Throwable(ni == 0);
|
||||||
|
|
||||||
|
ni = 0;
|
||||||
|
assertNotThrown!Throwable(ni == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Implicitly converts to $(D T).
|
Implicitly converts to $(D T).
|
||||||
Gets the value. $(D this) must not be in the null state.
|
$(D this) must not be in the null state.
|
||||||
*/
|
*/
|
||||||
alias get this;
|
alias get this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
Nullable!(size_t, size_t.max) indexOf(string[] haystack, string needle)
|
||||||
|
{
|
||||||
|
//Find the needle, returning -1 if not found
|
||||||
|
|
||||||
|
return Nullable!(size_t, size_t.max).init;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendLunchInvite(string name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//It's safer than C...
|
||||||
|
auto coworkers = ["Jane", "Jim", "Marry", "Fred"];
|
||||||
|
auto pos = indexOf(coworkers, "Bob");
|
||||||
|
if (!pos.isNull)
|
||||||
|
{
|
||||||
|
//Send Bob an invitation to lunch
|
||||||
|
sendLunchInvite(coworkers[pos]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Bob not found; report the error
|
||||||
|
}
|
||||||
|
|
||||||
|
//And there's no overhead
|
||||||
|
static assert(Nullable!(size_t, size_t.max).sizeof == size_t.sizeof);
|
||||||
|
}
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
import std.exception : assertThrown;
|
import std.exception : assertThrown;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue