libmir / mir-algorithm

Dlang Core Library
http://mir-algorithm.libmir.org
Other
174 stars 37 forks source link

const conversion with labels #469

Open jmh530 opened 5 months ago

jmh530 commented 5 months ago

There seems to be some weird behavior when you have a function that takes a slice with a const(T)* iterator and try to handle cases with labels. The errors I get as it is is that some of these match multiple functions for reasons that don't quite make sense. I know there's some part of the mir_slice code that converts things to const, but I've never really dug into it to understand how it works.

The code below doesn't have errors when you replace the const(T)* with T*. Alternately, if you replace the int*s with const(int)*s, then the errors go away.

/+dub.sdl:
dependency "mir-algorithm" version="*"
+/

import mir.ndslice.slice;
import mir.ndslice.allocation;
import std.stdio: writeln;

void foo(T)(Slice!(const(T)*, 2u, Contiguous) a)
{
    writeln(typeid(typeof(a)));
    writeln("here0");
}

void foo(T)(Slice!(const(T)*, 2u, Contiguous, int*) a)
{
    writeln(typeid(typeof(a)));
    writeln("here1");
}

void foo(T)(Slice!(const(T)*, 2u, Contiguous, int*, int*) a)
{
    writeln(typeid(typeof(a)));
    writeln("here2");
}

void main()
{
    auto X = slice!double(3, 3);
    auto X1 = slice!(double, int)(3, 3);
    auto X2 = slice!(double, int, int)(3, 3);

    writeln(typeid(typeof(X)));
    foo(X);
    writeln(typeid(typeof(X1)));
    foo(X1); //error
    writeln(typeid(typeof(X2)));
    foo(X2); //error

    writeln("done");
}
jmh530 commented 5 months ago

Anyway, the consequence of this is that it can be hard to write a function like below that works generically with labels and const T pointers.

void foo(T, Labels...)(Slice!(const(T)*, 2u, Contiguous, Labels) a) {}
9il commented 5 months ago

The lables almost not implemented.

9il commented 5 months ago

Mit uses alias this on toConst. Maybe updating toConst could help

jmh530 commented 5 months ago

@9il After looking at it for a bit, it is starting to make a bit more sense why you did it this way. The idea is to make the whole thing const, including both values and labels.

The only thing that really jumps out is that the alias toConst this only applies for when the type is not constant. Here: static if (!is(Slice!(const(Unqual!(PointerTarget!Iterator))*, N, kind) == This)) This only considers the case where the Iterator is const. What if the iterator is const, but the labels aren't?

And for whatever reason, this doesn't work but would make my life a lot easier if you could void foo(T, Labels...)(Slice!(const(T)*, 2u, Contiguous, staticMap!(ConstOfUnqualOfPointerTarget, Labels)) a)

You instead have to do something like:

void foo(T)(Slice!(const(T)*, 2u, Contiguous) a) {}
void foo(T, Label1)(Slice!(const(T)*, 2u, Contiguous, const(Label1)*) a) {}
void foo(T, Label1, Label2)(Slice!(const(T)*, 2u, Contiguous, const(Label1)*, const(Label2)*) a) {}