On 5/17/16 8:36 PM, H. S. Teoh via Digitalmars-d-announce wrote:
On Tue, May 17, 2016 at 08:19:48PM +0000, Vladimir Panteleev via
Digitalmars-d-announce wrote:
On Tuesday, 17 May 2016 at 17:26:59 UTC, Steven Schveighoffer wrote:
However, it's perfectly legal for a front function not to be tagged
@property.
BTW, where is this coming from? Is it simply an emergent property of
the existing implementations of isInputRange and ElementType, or is it
actually by design?
This is very bad. The range API does not mandate that .front must be a
function. I often write ranges where .front is an actual struct variable
that gets updated by .popFront. Now you're saying that my range won't
work with some code, because they call .front() (which is a compile
error when .front is a variable, not a function)?
My goodness no!
People, please, my point is simply that is(typeof(someRange.front) ==
ElementType!(typeof(someRange))) DOESN'T ALWAYS WORK.
Here is the (long standing) definition of isInputRange:
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
(inout int = 0)
{
R r = R.init; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
}));
}
Not there is no check for is(typeof(r.front)) to be some certain thing.
So this is a valid range:
struct AllZeros
{
int front() { return 0; }
enum empty = false;
void popFront() {}
}
Yet, is(typeof(AllZeros.init.front) == int) will be false. This is the
line of code from the article that I suggested to add the parens to.
Because in that particular case, string.front is a function, not a
field. The code in question is NOT GENERIC, it's just showing that
string.front is not the same as string[0]. It's very specific to string.
In the old days (i.e., 1-2 years ago), isForwardRange!R will return
false if .save is not marked @property. I thought isInputRange!R did the
same for .front, or am I imagining things? Did somebody change this
recently?
You are imagining that someInputRange.front ever required that. In fact,
it would have had to go out of its way to do so (because isInputRange
puts no requirements on the *type* of front, except that it returns a
non-void value).
But you are right that save did require @property at one time. Not (In
my opinion) because it meant to, but because it happened to check the
type of r.save against a type (namely, that .save returns its own type).
At the same time, I fixed all the isXXXRange traits so @property is not
required anywhere. In particular, isRandomAccessRange required r.front
to be @property, even when isInputRange didn't (again, IMO
unintentionally). Here is the PR: https://github.com/dlang/phobos/pull/3276
-Steve