On Monday, 1 August 2016 at 15:06:54 UTC, Jonathan M Davis wrote:
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
This is exactly what my question is about. I don't think, that it
doesn't make sense (and isn't a good idea) to index with an
arbitrary type, too.
So, how I can define/design a type, which is not an int/size_t,
but has one to be able to index with it?
And if the __compiles trait is the way to go with... well then
that's just how it is...