Indexing with an arbitrary type

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Aug 3 07:23:59 PDT 2016


On Wednesday, August 03, 2016 09:21:13 Alex via Digitalmars-d-learn wrote:
> On Monday, 1 August 2016 at 16:09:50 UTC, Alex wrote:
> > On Monday, 1 August 2016 at 15:51:58 UTC, Jonathan M Davis
> > wrote:
> > template isIndexable(I, T)
> > {
> >
> >     enum isIndexable = __traits(compiles, T.init[I.init]);
> >
> > }
>
> As a last question afterwards:
> Is it possible to create such an isIndexable template without
> templating over the type T?
> something like
>
> template isIndexable(I)
> {
>      enum isIndexable = __traits(compiles, ???[I.init]);
> }
>
> sure, I could use
>
> __traits(compiles, (int[]).init[I.init])
>
> but is this the intended way to go?

__traits(compiles, ...) is testing whether the code in question compiles.
What you need to test is whether the object is indexable by the other, and
that would mean needing both the type being indexed and the type which is
the index. Just because one particular type is indexable by whatever the
index type is doesn't mean that another will be. For instance, int[] is only
going to be indexable by size_t and anything that implicitly converts to
size_t. Testing whether int[] is indexable with size_t isn't going to say
anything about whether int[string] is indexable with size_t. If you want to
test that int[string] is indexable with size_t, you'll need to actually test
it with size_t, not int[] - the same goes for any other combinaton of object
to index and object that is the index. If you're just typing out the whole
thing every time, then you can do stuff like

auto foo(I, T)(I index, T obj)
    if(__traits(compiles, obj[index]))
{
    ...
}

because you have actual objects to deal with, whereas with a template
written to encapsulate that test, you only have the types. The init property
is just an easy way to get at an object of the type without declaring it or
worrying about how one is constructed. But to do the same test as that
example with a separate template, you're going to need both types. e.g.

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

If you don't have both, you're not doing the same test, and it's impossible
to test that one type is indexable by another without using both types in
the test. To only have one of the two types in a test would be like trying t
to test whether a function can be called on a particular type while only
having the function in the test and not the type. It doesn't work.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list