Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 70 additions & 3 deletions std/typecons.d
Original file line number Diff line number Diff line change
Expand Up @@ -2185,6 +2185,69 @@ Params:
_isNull = false;
}

/**
If they are both null, then they are equal. If one is null and the other
is not, then they are not equal. If they are both non-null, then they are
equal if their values are equal.
*/
bool opEquals()(auto ref const(typeof(this)) rhs) const
{
if (_isNull)
return rhs._isNull;
if (rhs._isNull)
return false;
return _value == rhs._value;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of accessing a pseudo private member, why not return _value == rhs.get;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would you do that? This is opEquals. It's normal to access the member variables of the two variables to compare them. Calling get would just add unnecessary overhead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because you're accessing an undocumented public member, something that we're trying to move away from and make these members private. _value should really be private or package.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is private. And since this is a member function, it's accessible. The fact that it's from another instance doesn't matter. The normal thing to do in a function like opEquals or opCmp is to use the member variables directly, and it's often the case that that's the only way that they can be used, because they're private. It would be incredibly bizarre to call a member function to access a member to compare it in opEquals rather than just accessing it directly.

}

/// Ditto
bool opEquals()(auto ref const(T) rhs) const
{
return _isNull ? false : rhs == _value;
}

///
@safe unittest
{
Nullable!int empty;
Nullable!int a = 42;
Nullable!int b = 42;
Nullable!int c = 27;

assert(empty == empty);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For documentation sake, I would add a line here that says assert(empty.isNull);

assert(empty == Nullable!int.init);
assert(empty != a);
assert(empty != b);
assert(empty != c);

assert(a == b);
assert(a != c);

assert(empty != 42);
assert(a == 42);
assert(c != 42);
}

@safe unittest
{
// Test constness
immutable Nullable!int a = 42;
Nullable!int b = 42;
immutable Nullable!int c = 29;
Nullable!int d = 29;
immutable e = 42;
int f = 29;
assert(a == a);
assert(a == b);
assert(a != c);
assert(a != d);
assert(a == e);
assert(a != f);

// Test rvalue
assert(a == const Nullable!int(42));
assert(a != Nullable!int(29));
}

template toString()
{
import std.format : FormatSpec, formatValue;
Expand Down Expand Up @@ -2317,15 +2380,19 @@ Returns:
///
@system unittest
{
import core.exception : AssertError;
import std.exception : assertThrown, assertNotThrown;

Nullable!int ni;
int i = 42;
//`get` is implicitly called. Will throw
//an AssertError in non-release mode
assertThrown!Throwable(ni == 0);
assertThrown!AssertError(i = ni);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

==?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. == never asserts now, whereas = does.

assert(i == 42);

ni = 0;
assertNotThrown!Throwable(ni == 0);
ni = 5;
assertNotThrown!AssertError(i = ni);
assert(i == 5);
}

/**
Expand Down