@@ -4836,9 +4836,48 @@ if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, r.front)) == bool))
48364836 assert (equal(uniq([ 1 , 1 , 2 , 1 , 1 , 3 , 1 ]), [1 , 2 , 1 , 3 , 1 ]));
48374837}
48384838
4839+ // /
4840+ @trusted unittest
4841+ {
4842+ import std.algorithm.comparison : equal;
4843+
4844+ struct S
4845+ {
4846+ int i;
4847+ string s;
4848+ }
4849+
4850+ auto arr = [ S(1 , " a" ), S(1 , " b" ), S(2 , " c" ), S(2 , " d" ) ];
4851+
4852+ // Let's consider just the 'i' member for equality
4853+ auto r = arr.uniq! ((a, b) => a.i == b.i);
4854+ assert (r.equal([S(1 , " a" ), S(2 , " c" )]));
4855+ assert (r.front == S(1 , " a" ));
4856+ assert (r.back == S(2 , " c" ));
4857+
4858+ r.popBack;
4859+ assert (r.back == S(1 , " a" ));
4860+ assert (r.front == r.back);
4861+
4862+ r.popBack;
4863+ assert (r.empty);
4864+
4865+ import std.exception : assertThrown;
4866+
4867+ assertThrown! Error(r.front);
4868+ assertThrown! Error(r.back);
4869+ assertThrown! Error(r.popFront);
4870+ assertThrown! Error(r.popBack);
4871+ }
4872+
48394873private struct UniqResult (alias pred, Range )
48404874{
4841- Range _input;
4875+ private Range _input;
4876+ static if (isBidirectionalRange! Range )
4877+ {
4878+ private ElementType! Range _back;
4879+ private bool _isInBack;
4880+ }
48424881
48434882 this (Range input)
48444883 {
@@ -4853,17 +4892,33 @@ private struct UniqResult(alias pred, Range)
48534892 void popFront ()
48544893 {
48554894 assert (! empty, " Attempting to popFront an empty uniq." );
4895+ static if (isBidirectionalRange! Range )
4896+ {
4897+ if (_input.empty)
4898+ {
4899+ _isInBack = false ;
4900+ return ;
4901+ }
4902+ }
4903+
48564904 auto last = _input.front;
48574905 do
48584906 {
4859- _input.popFront() ;
4907+ _input.popFront;
48604908 }
48614909 while (! _input.empty && pred(last, _input.front));
48624910 }
48634911
48644912 @property ElementType! Range front()
48654913 {
48664914 assert (! empty, " Attempting to fetch the front of an empty uniq." );
4915+ static if (isBidirectionalRange! Range )
4916+ {
4917+ if (_input.empty && _isInBack)
4918+ {
4919+ return _back;
4920+ }
4921+ }
48674922 return _input.front;
48684923 }
48694924
@@ -4872,18 +4927,33 @@ private struct UniqResult(alias pred, Range)
48724927 void popBack ()
48734928 {
48744929 assert (! empty, " Attempting to popBack an empty uniq." );
4875- auto last = _input.back;
4876- do
4930+ if (_input.empty)
4931+ {
4932+ _isInBack = false ;
4933+ }
4934+ else
48774935 {
4878- _input.popBack();
4936+ _isInBack = true ;
4937+ _back = _input.back;
4938+ ElementType! Range last;
4939+ do
4940+ {
4941+ last = _input.back;
4942+ _input.popBack;
4943+ }
4944+ while (! _input.empty && pred(_back, _input.back));
4945+ _back = last;
48794946 }
4880- while (! _input.empty && pred(last, _input.back));
48814947 }
48824948
48834949 @property ElementType! Range back()
48844950 {
48854951 assert (! empty, " Attempting to fetch the back of an empty uniq." );
4886- return _input.back;
4952+ if (! _isInBack)
4953+ {
4954+ popBack;
4955+ }
4956+ return _back;
48874957 }
48884958 }
48894959
@@ -4893,7 +4963,17 @@ private struct UniqResult(alias pred, Range)
48934963 }
48944964 else
48954965 {
4896- @property bool empty() { return _input.empty; }
4966+ @property bool empty()
4967+ {
4968+ static if (isBidirectionalRange! Range )
4969+ {
4970+ return _input.empty && ! _isInBack;
4971+ }
4972+ else
4973+ {
4974+ return _input.empty;
4975+ }
4976+ }
48974977 }
48984978
48994979 static if (isForwardRange! Range )
0 commit comments