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