Iterating over 0..T.max

Kai Meyer kai at unixlords.com
Wed Mar 9 12:24:57 PST 2011


On 03/09/2011 09:09 AM, Magnus Lie Hetland wrote:
> In a (template) data structure I'm working on, I had the following thinko:
>
> auto a = new T[n];
> foreach (T i, ref e; a) {
> e = i;
> }
>
> Then I instantiated it with T=bool, and n=256. Infinite loop, of course
> -- the problem being that i wraps around to 0 after the last iteration.
> Easily fixed, and not that much of a problem (given that I caught it) --
> I'll just use e = cast(T) i. (Of course, even with that solution, I'd
> get wrap problems if n=257, but I just want to make sure I allow T.max
> as a size.)
>
> But I'm wondering: given D's excellent valua range propagations and
> overflow checking, would it be possible to catch this special case
> (i.e., detect when the array can be too long for the index type)? Or are
> any other safeguards possible to prevent this sort of thing?
>

I don't see how that works in dmd2, and I don't have much experience 
with dmd1, so I'll admit that this may be different on dmd1. I get 
compilation errors with your code:

import std.stdio;

void main()
{
     make_new!(bool)(256);
}

void make_new(T)(size_t n)
{
     auto a = new T[n];
     foreach (T i, ref e; a) {
         e = i;
     }
}

This gives me:
tmax.d(12): Error: operation not allowed on bool 'i'
tmax.d(5): Error: template instance tmax.make_new!(bool) error instantiating

As far as I understand, a foreach over an array makes the first value 
(i) a uint for the index, and the second value (e) a copy of the value 
in the array (in our case a bool).

import std.stdio;

void main()
{
     make_new!(bool)(1);
}

void make_new(T)(size_t n)
{
     auto a = new T[n];
     writef("%s\n", typeof(a).stringof);
     foreach (i,e; a) {
         writef("%s\n", typeof(i).stringof);
         writef("%s\n", typeof(e).stringof);
     }
}

/*
Output:
bool[]
uint
bool
*/



But to the question about boundaries, 'i' is a uint (size_t), and on a 
4GB machine, I can't call "auto a = new bool[size_t.max];". The program 
segfaults. size_t.max / 2 for a size gives me "Memory allocation 
failed". size_t.max / 4 works fine.

I'm not sure how to get a program to do what you describe.


More information about the Digitalmars-d-learn mailing list