On Wednesday, 3 August 2016 at 17:56:54 UTC, Jonathan M Davis
wrote:
int is comparable, but it's not going to index float[string].
Only a string is going to do that. Similarly, long is
comparable, but on a 32-bit system, it won't index int[],
because it's larger than size_t, which is the actual index type
for int[].
If all that your code cares about is that type T is comparable,
then sure, test that it's comparable. But if it's going to pass
a value of type T to the index operator of type U, then T's
index operator needs to accept type U. And a type like SysTime
from std.datetime is comparable, but it sure isn't going to
work as an index for int[].
This is a good point, I admit. But still, isn't it the indexable
objects task to define the opIndex method to take a particular
index?
And being comparable isn't enough to guarantee that T is going
to work.
In fact, there isn't even a guarantee that U's opIndex even
takes a type
that's comparable. Maybe it's a weird socket type that use
opIndex to
connect to a particular IP address rather than having a
properly named
function for that, and it takes an Address object that isn't
comparable.
Yes, that would be weird and likely bad design, but there's
nothing about
opIndex that prevents it. So, testing for whether U was
comparable wouldn't
necessarily tell you whether it could be used to index a type.
Yes. I tested a struct, which has a Nullable value in it aliased
to this and with an opCmp defined with respect to the Nullable
value and it didn't worked, too.
I find this strange, because if I already define, how the value
should behave, if it is in the null state, I would assume, it
should be able to index with it too...
But even if everyone restricts themselves to using opIndex in
sane ways, and all index types are comparable, not all types
take the same index types. So, if you just test that the index
type is comparable without testing it against the type that
it's actually going to index, then your template constraint
will let through types that won't be compatible and will result
in a compilation error.
Yes. But this is just a compilation error... It says, well, there
is a mistake in the code.
What I want is to achieve a constraint on my own type, which is
at this time point defined just as
alias MyType = size_t;
but later on, this could maybe become a struct, and I still want
to be able to handle it like an index.
The opIndex methods of the surrounding objects are already
defined in terms of the MyType, so the problem of interacting
does not play a big role. The question is how to describe the
minimal requirement on the type itself...
Maybe I don't understand enough about what you're trying to do
and am not giving the best advice as a result, but if you have
a function that takes a two arguments where one is supposed to
be an index, and the other is supposed to be an object to be
indexed, then the only template constraint that will prevent
types getting through which won't compile when the code
actually uses the index operator is to test that the object to
be indexed can be indexed by the index object. Testing that the
index type is comparable is completely insufficient.
Yes... I can confirm this...
the last line of this code inside the main gives an error...
https://dpaste.dzfl.pl/043d1deb9073
It will work with a particular set of types, but it will not
work with all indexable types, and if a types that don't work
together are passed to that function, then you will get a
compilation error inside of the function instead of at the
template constraint catching it.
The code above, gives even a runtime error, which is much
worse... It would be enough, I think, to assert, that MyType
resolves to the particular set of types...
Which are these? Is it possible to write this kind of template?