digitalmars.D.learn - Better way to compromise on the lack of template alias resolution
- Elfstone (44/44) Mar 14 2023 ```D
- ionkare (32/77) Mar 14 2023 **just a noob seeing if can solve this no idea if this is vaild
- Elfstone (21/112) Mar 14 2023 This requires coding inside Matrix, while my Matrix is only about
- Paul Backus (31/41) Mar 15 2023 Currently the best workaround for this is to define `Vector` as a
- Elfstone (4/36) Mar 15 2023 There's a problem with this approach: I'll have to specialize
```D struct Matrix(S, size_t M, size_t N) { } alias Vector(S, size_t N) = Matrix!(S, N, 1); enum isVector(V) = is(V == Vector!(S, N), S, size_t N); // it doesn't work enum isVectorCorrect(V) = is(V == Matrix!(U, N, 1), U, size_t N); // the "correct" way and how much I like to REPEAT myself! void foo(U)(Vector!(U, 3) a) { } void bar(U)(U a) if (isVector!U) { } void main() { import std.stdio; Vector!(float, 3) v; foo(v); // Error: none of the overloads of template `app.doSomething` are callable using argument types `!()(Matrix!(float, 3LU, 1LU)) bar(v); // failed constraint isVector!U } ``` I went back to some of my old code and couldn't stand what I had ended up with - If I already have a well-defined `Vector`, why do I have to write extra code to implement `isVector`, and use `isVector` instead of simply declaring the param to be `Vector`? But that's simply the current state: it looks like DIP1023 isn't going anywhere, and I'm not a compiler expert. Note that I had to repeat `Matrix!(S, N, 1)` to for both `Vector` and `isVector`. Is there a way around this?! -- It can get worse. ```D alias Vec2(S) = Vector!(S, 2); alias Vec3(S) = Vector!(S, 3); enum isVec3(V) = is(V == Matrix!(S, 2, 1), S); enum isVec3(V) = is(V == Matrix!(S, 3, 1), S); void foobar(U)(U v) if (isVec3!U); ``` It works, but it hurts my eyes.
Mar 14 2023
On Tuesday, 14 March 2023 at 10:19:24 UTC, Elfstone wrote:```D struct Matrix(S, size_t M, size_t N) { } alias Vector(S, size_t N) = Matrix!(S, N, 1); enum isVector(V) = is(V == Vector!(S, N), S, size_t N); // it doesn't work enum isVectorCorrect(V) = is(V == Matrix!(U, N, 1), U, size_t N); // the "correct" way and how much I like to REPEAT myself! void foo(U)(Vector!(U, 3) a) { } void bar(U)(U a) if (isVector!U) { } void main() { import std.stdio; Vector!(float, 3) v; foo(v); // Error: none of the overloads of template `app.doSomething` are callable using argument types `!()(Matrix!(float, 3LU, 1LU)) bar(v); // failed constraint isVector!U } ``` I went back to some of my old code and couldn't stand what I had ended up with - If I already have a well-defined `Vector`, why do I have to write extra code to implement `isVector`, and use `isVector` instead of simply declaring the param to be `Vector`? But that's simply the current state: it looks like DIP1023 isn't going anywhere, and I'm not a compiler expert. Note that I had to repeat `Matrix!(S, N, 1)` to for both `Vector` and `isVector`. Is there a way around this?! -- It can get worse. ```D alias Vec2(S) = Vector!(S, 2); alias Vec3(S) = Vector!(S, 3); enum isVec3(V) = is(V == Matrix!(S, 2, 1), S); enum isVec3(V) = is(V == Matrix!(S, 3, 1), S); void foobar(U)(U v) if (isVec3!U); ``` It works, but it hurts my eyes.**just a noob seeing if can solve this no idea if this is vaild code** ```D // T int, double, float // N element // V number of elements / weight template Matrix(T, size_t N = 2, size_t V = 1) { struct Matrix { static if (is(Matrix!(T, N, V))) { alias enum isVec3 = N == 3; alias enum isVec2 = N == 2; alias enum isVaildVec = (isVec2 || isVec3); } } } bool foo(T)(Matrix!T element) { return element.isVaildVec; } void main() { import std.stdio : writeln; // defaults to vec2 of 1 Matrix!int c; c.foo.writeln; c.writeln; } ```
Mar 14 2023
On Tuesday, 14 March 2023 at 17:57:38 UTC, ionkare wrote:On Tuesday, 14 March 2023 at 10:19:24 UTC, Elfstone wrote:This requires coding inside Matrix, while my Matrix is only about Matrix operations. The thing is that I can create aliases anywhere, outside of the original module. I can use the the aliases everywhere except as template parameters, because D simply won't match template alias parameters, and I could not find a way to create a constraint based on an existing alias, which defeats the supposed meaning and purpose of `alias`. I hope some Samaritan in the community will actually "see the value" in this, pick up DIP1023 or push another. Before that happens, if ever, all I can do is restraining myself from using template alias parameters, 'cause it IS in fact broken. How does anyone see the following code and not call the language bugged? ```D writeln(is(Vec2!float == Vec2!S, S)); // false ``` Actually I'd be happy if this code works, because then I can create a constraint based on the alias. But I guess it requires the same machanism to make template alias parameters work.```D struct Matrix(S, size_t M, size_t N) { } alias Vector(S, size_t N) = Matrix!(S, N, 1); enum isVector(V) = is(V == Vector!(S, N), S, size_t N); // it doesn't work enum isVectorCorrect(V) = is(V == Matrix!(U, N, 1), U, size_t N); // the "correct" way and how much I like to REPEAT myself! void foo(U)(Vector!(U, 3) a) { } void bar(U)(U a) if (isVector!U) { } void main() { import std.stdio; Vector!(float, 3) v; foo(v); // Error: none of the overloads of template `app.doSomething` are callable using argument types `!()(Matrix!(float, 3LU, 1LU)) bar(v); // failed constraint isVector!U } ``` I went back to some of my old code and couldn't stand what I had ended up with - If I already have a well-defined `Vector`, why do I have to write extra code to implement `isVector`, and use `isVector` instead of simply declaring the param to be `Vector`? But that's simply the current state: it looks like DIP1023 isn't going anywhere, and I'm not a compiler expert. Note that I had to repeat `Matrix!(S, N, 1)` to for both `Vector` and `isVector`. Is there a way around this?! -- It can get worse. ```D alias Vec2(S) = Vector!(S, 2); alias Vec3(S) = Vector!(S, 3); enum isVec3(V) = is(V == Matrix!(S, 2, 1), S); enum isVec3(V) = is(V == Matrix!(S, 3, 1), S); void foobar(U)(U v) if (isVec3!U); ``` It works, but it hurts my eyes.**just a noob seeing if can solve this no idea if this is vaild code** ```D // T int, double, float // N element // V number of elements / weight template Matrix(T, size_t N = 2, size_t V = 1) { struct Matrix { static if (is(Matrix!(T, N, V))) { alias enum isVec3 = N == 3; alias enum isVec2 = N == 2; alias enum isVaildVec = (isVec2 || isVec3); } } } bool foo(T)(Matrix!T element) { return element.isVaildVec; } void main() { import std.stdio : writeln; // defaults to vec2 of 1 Matrix!int c; c.foo.writeln; c.writeln; } ```
Mar 14 2023
On Tuesday, 14 March 2023 at 10:19:24 UTC, Elfstone wrote:I went back to some of my old code and couldn't stand what I had ended up with - If I already have a well-defined `Vector`, why do I have to write extra code to implement `isVector`, and use `isVector` instead of simply declaring the param to be `Vector`? But that's simply the current state: it looks like DIP1023 isn't going anywhere, and I'm not a compiler expert. Note that I had to repeat `Matrix!(S, N, 1)` to for both `Vector` and `isVector`. Is there a way around this?!Currently the best workaround for this is to define `Vector` as a `struct` with `alias this` instead of as an `alias`: ```d struct Matrix(S, size_t M, size_t N) { // ... } //alias Vector(S, size_t N) = Matrix!(S, N, 1); struct Vector(S, size_t N) { Matrix!(S, N, 1) data; alias data this; // forward constructor calls to wrapped object this(this This, Args...)(auto ref Args args) { import core.lifetime: forward; data = forward!args; } } void foo(U)(Vector!(U, 3) a) { import std.stdio; writeln("Called with U = ", U.stringof); } void main() { Vector!(float, 3) v; foo(v); // ok } ```
Mar 15 2023
On Wednesday, 15 March 2023 at 19:22:32 UTC, Paul Backus wrote:On Tuesday, 14 March 2023 at 10:19:24 UTC, Elfstone wrote:There's a problem with this approach: I'll have to specialize `Vector Matrix.opBinary(Vector)`. I don't plan to separate my Vector from Matrix yet. :([...]Currently the best workaround for this is to define `Vector` as a `struct` with `alias this` instead of as an `alias`: ```d struct Matrix(S, size_t M, size_t N) { // ... } //alias Vector(S, size_t N) = Matrix!(S, N, 1); struct Vector(S, size_t N) { Matrix!(S, N, 1) data; alias data this; // forward constructor calls to wrapped object this(this This, Args...)(auto ref Args args) { import core.lifetime: forward; data = forward!args; } } void foo(U)(Vector!(U, 3) a) { import std.stdio; writeln("Called with U = ", U.stringof); } void main() { Vector!(float, 3) v; foo(v); // ok } ```
Mar 15 2023