Range.init does not imply Range.empty==true

Maxim Fomin maxim at maxim-fomin.ru
Thu Dec 20 23:09:20 PST 2012


On Thursday, 20 December 2012 at 21:10:24 UTC, H. S. Teoh wrote:
> But .init isn't merely used when you explicitly invoke it. It's 
> the
> default value of struct fields, for example (see below).
>
>
> No we can't. For example:
>
> 	auto someRangeFunction(RoR)(RoR ror) {
> 		struct Helper {
> 			RoR _ror;
> 			ElementType!R _current;
>
> 			this(RoR r) {
> 				_ror = r;
> 				assert(_current.empty);
> 			}
> 		}
> 		return Helper(ror);
> 	}
>
> If RoR is an array of class objects, the assert line will 
> segfault
> because _current.init is null. Conceptually speaking, I agree 
> that a
> null object is an empty range, but in code, .empty is undefined 
> because
> you can't invoke a method through a null reference.
>
>
> T

Note, assumption that structs and allocated classes at runtime 
are default in accordance with their T.init can be easily broken. 
Also they can default to different values across runtime of 
program.

import std.stdio;

class A { int x = 5; }

struct S { int x = 5; A a; }

struct Z { S s; }

void main()
{
	assert(S.init==S(5, null)); writeln(S.init); // S(5, null)
	A a = new A;
	assert(a.x != 5); writeln(a.x); // may pass and print anything
	S* s1 = new S;
	assert(s1.x != 5 && s1.a && s1.a.x != 5); //may pass
	writeln(s1.x, s1.a, s1.a.x); // may be anything
	S s2;
	assert(s2.x != 5 && s2.a && s2.a.x != 5); //also may pass
	writeln(s2.x, s2.a, s2.a.x); // may default to anything
	Z z;
	writeln(z); //also can have arbitrly values
}


More information about the Digitalmars-d mailing list