Indexing with an arbitrary type

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Aug 1 08:06:54 PDT 2016


On Monday, August 01, 2016 14:46:03 Alex via Digitalmars-d-learn wrote:
> On Monday, 1 August 2016 at 13:52:56 UTC, Jonathan M Davis wrote:
> > An array does not implement RandomAccessFinite, which is an
> > interface that you created. So, a function that takes a
> > RandomAccessFinite is not going to accept an array. A dynamic
> > array will match isRandomAccessRange, but that has nothing to
> > do with interfaces.
>
> It's ok for me to say, that some types do not implement an
> interface to show some abilities, even if the interface, which
> has to be implemented to show the same abilities is
> given/known/public/exposed... etc...
> So, I think this part is ok now, I think...

I'm afraid that I don't know what you're talking about, but if what you have
is working, then great. But while arrays can pass template constraints, they
can't implement interfaces, so what you had before didn't really seem like
it was going to work.

> >> But the main question is about the other part, about the
> >> constraint to the first parameter to my functions.
> >> It seems strange to me to use "isIntegral" here, as this is
> >> some
> >> kind of unrelated for something used as an index.
> >> Is there anything more appropriate to check? What kind of
> >> interface/trait has an index to fulfill?
> >
> > What's strange? If you want to accept any integer type, then
> > isIntegral!T would do it. A _better_ thing to do would be to
> > make it so that it's just size_t and not templatize the type,
> > since indices really should be size_t normally (and if the
> > system is 32-bit, then isIntegral!T will accept long and ulong,
> > whereas size_t is uint, and if you pass a long, you'll get a
> > compilation error for arrays, since they take size_t for
> > indexing; it won't matter for 64-bit though, since size_t is
> > ulong there). So,
> >
> > auto f1(R)(size_t index, R range)
> >
> >     if(isRandomAccessRange!R)
> >
> > {
> >
> >     return range[index];
> >
> > }
> >
> > would be better, but aside from the 32-bit issues, isIntegral
> > will work.
> >
> > - Jonathan M Davis
>
> This goes in a different direction I want to. I don't have
> anything against simplification to size_t, indeed I have it in
> this way currently. But what I want is something like the
> following:
>
> having
>      alias MyIndex = int
> and
>      MyIndex s = MyInd(1);
>      writeln(f1(s, arr)); //gives 42, as expected
>
> Now, I want to define a
> struct S
> {
>      int index;
>      ??? what else ??? // alias index this; doesn't help
> }
> and still being able to have
>      alias MyIndex = S
> and nothing else should be changed.

If you want a template constraint that checks that a type works with the
index operator on a type, and you're not restricting it to something like
size_t, then you're just going to have to check whether the expression is
going to compile. Also, that is incompatible with random access ranges.
Random access ranges are expected to work with size_t, and while
isRandomAccessRange isn't currently quite that restrictive, it does check
that r[1] compiles, so the index operator is going to have to accept
integers at minimum. If you want a completely generic index operator, and
you want a template constraint for it, you're pretty much going to have to
test that it compiles. e.g.

auto fun(I, T)(I index, T obj)
    if(__traits(compiles, obj[index]))
{
    return obj[index];
}

or if you want a reusable template, you can do something like

template isIndexable(I, T)
{
    enum isIndexable = __traits(compiles, T.init[I.init]);
}

auto fun(I, T)(I index, T obj)
    if(isIndexable!(I, T))
{
    return obj[index];
}

Personally, I think that having code that accepts any type that can be
indexable with any type isn't a particularly good idea, because odds are, it
won't actually work, because those different types will work quite
differently (e.g. associative arrays are indexable with stuff other than
size_t, but they're really not interchangeable with dynamic arrays or static
arrays, which use size_t). And anything that wants to be interchangeable
with a dynamic array or be usable as a random access range should be using
size_t to index. But if you actually have code where it makes sense to deal
with types that can take all kinds of random stuff as indices, then
something like I posted above should work.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list