digitalmars.D.learn - Parameters declared as the alias of a template won't accept the
- Elfstone (40/40) Apr 30 2022 module test;
- Tejas (5/10) Apr 30 2022 AFAICT, I'm afraid you'll have to stick to `dot2` 🙁
- Elfstone (5/17) May 01 2022 Thanks a lot! So this really is a D "feature".
- JG (21/43) May 01 2022 I guess the current best is something like:
- JG (11/40) May 01 2022 The static assert isn't needed.
- Elfstone (3/15) May 01 2022 Great, I'm using the constraint, until it's fixed.
- Mike Parker (4/7) May 01 2022 The DIP was postponed. I can contact the author to see if he
- Elfstone (16/24) May 01 2022 Thanks. This breaks a lot of things. I don't know the reason
- Mike Parker (34/41) May 01 2022 At the bottom of the DIP you can find a link to the first
- Loara (20/62) May 02 2022 Template deduction for aliased function parameter is a very
- JG (12/31) May 02 2022 I don't really see what your example is trying to show. This also
- Loara (8/43) May 03 2022 Yeah I know, but I'm trying to show that allowing aliased
- Stanislav Blinov (11/30) May 02 2022 Why? That's the issue. It is very possible to deduce T here.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (24/48) May 02 2022 That's fine because D does not promise to solve such problems. It
- Stanislav Blinov (11/65) May 02 2022 Words, dear guru. Words have a meaning. It is very possible to
- =?UTF-8?Q?Ali_=c3=87ehreli?= (21/65) May 03 2022 No, the compiler does not parse all templates. Only the ones that needs
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (11/14) May 03 2022 Ok, so C++ has similar limitations when you have a template with
- ag0aep6g (5/21) May 02 2022 I take it your answer is that T must be int. But that's nonsense.
- Stanislav Blinov (4/25) May 02 2022 That's not my answer. And it is nonsense, because my answer is -
- JG (5/24) May 02 2022 Maybe I am being silly, but it isn't possible to determine T
- Loara (5/24) May 03 2022 No, an alias is not a type and it'll be immediately
- Elfstone (8/29) May 02 2022 Yeah, I understand some cases are impossible, and to be avoided.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (10/17) May 03 2022 I haven't read all of the posts in this thread, but D in general
- bauss (4/7) May 04 2022 I don't believe those two words are mutually exclusive.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (5/6) May 04 2022 Alright, but we need a DIP to get the enhancement which can be
module test; struct MatrixImpl(S, size_t M, size_t N) { } template Vector(S, size_t N) { alias Vector = MatrixImpl!(S, 1, N); } nogc S dot1(S, size_t N)(in Vector!(S, N) lhs, in Vector!(S, N) rhs) { return 0; } nogc S dot2(S, size_t N)(in MatrixImpl!(S, 1, N) lhs, in MatrixImpl!(S, 1, N) rhs) { return 0; } unittest { import std.stdio; Vector!(float, 2) a, b; dot1(a, b); // Error: none of the overloads of template `test.dot1` are callable using argument types `!()(MatrixImpl!(float, 1LU, 2LU), MatrixImpl!(float, 1LU, 2LU))` // Candidate is: `dot1(S, ulong N)(in Vector!(S, N) lhs, in Vector!(S, N) rhs)` dot2(a, b); // compiles static if (is(Vector!(float, 2) == MatrixImpl!(float, 1, 2))) { writeln("WTH"); // prints } } It's natural to declare it the way dot1 is declared, isn't it? Is this a bug? Or I simply can't assume alias works the way I thought it would. Can I work around it, without falling back to the abominable dot2?
Apr 30 2022
On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone wrote:module test; struct MatrixImpl(S, size_t M, size_t N) { } [...]AFAICT, I'm afraid you'll have to stick to `dot2` 🙁 This DIP I believe does what you want but... It wasn't looked upon favorably... https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1023.md
Apr 30 2022
On Sunday, 1 May 2022 at 06:42:26 UTC, Tejas wrote:On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone wrote:Thanks a lot! So this really is a D "feature". The current behaviour is so broken. It makes no sense, for a language user at least. I don't understand why it's not yet solved, if it's a known issue.module test; struct MatrixImpl(S, size_t M, size_t N) { } [...]AFAICT, I'm afraid you'll have to stick to `dot2` 🙁 This DIP I believe does what you want but... It wasn't looked upon favorably... https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1023.md
May 01 2022
On Sunday, 1 May 2022 at 07:59:57 UTC, Elfstone wrote:On Sunday, 1 May 2022 at 06:42:26 UTC, Tejas wrote:I guess the current best is something like: ```d enum isVector(V) = is(V==MatrixImpl!(S,1,N),S,size_t N); nogc auto dot1(V)(in V lhs, in V rhs) if(isVector!V) { return dot2(lhs,rhs); } ``` or ```d enum isVector(V) = is(V==MatrixImpl!(S,1,N),S,size_t N); nogc auto dot1(V)(in V lhs, in V rhs) if(isVector!V) { static if(is(V==MatrixImpl!(S,1,N),S,N)) { S ret=0; return ret; } static assert("This should never been shown"); } ```On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone wrote:Thanks a lot! So this really is a D "feature". The current behaviour is so broken. It makes no sense, for a language user at least. I don't understand why it's not yet solved, if it's a known issue.module test; struct MatrixImpl(S, size_t M, size_t N) { } [...]AFAICT, I'm afraid you'll have to stick to `dot2` 🙁 This DIP I believe does what you want but... It wasn't looked upon favorably... https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1023.md
May 01 2022
On Sunday, 1 May 2022 at 11:34:49 UTC, JG wrote:On Sunday, 1 May 2022 at 07:59:57 UTC, Elfstone wrote:The static assert isn't needed. ```d enum isVector(V) = is(V==MatrixImpl!(S,1,N),S,size_t N); nogc auto dot1(V)(in V lhs, in V rhs) if(isVector!V) { static if(is(V==MatrixImpl!(S,1,N),S,N)) { S ret=0; return ret; } } ```On Sunday, 1 May 2022 at 06:42:26 UTC, Tejas wrote:I guess the current best is something like: ```d enum isVector(V) = is(V==MatrixImpl!(S,1,N),S,size_t N); nogc auto dot1(V)(in V lhs, in V rhs) if(isVector!V) { return dot2(lhs,rhs); } ``` or ```d enum isVector(V) = is(V==MatrixImpl!(S,1,N),S,size_t N); nogc auto dot1(V)(in V lhs, in V rhs) if(isVector!V) { static if(is(V==MatrixImpl!(S,1,N),S,N)) { S ret=0; return ret; } static assert("This should never been shown"); } ```[...]Thanks a lot! So this really is a D "feature". The current behaviour is so broken. It makes no sense, for a language user at least. I don't understand why it's not yet solved, if it's a known issue.
May 01 2022
On Sunday, 1 May 2022 at 11:37:28 UTC, JG wrote:On Sunday, 1 May 2022 at 11:34:49 UTC, JG wrote:Great, I'm using the constraint, until it's fixed. Will it be fixed though? The DIP that Tejas linked is from 2020!!![...]The static assert isn't needed. ```d enum isVector(V) = is(V==MatrixImpl!(S,1,N),S,size_t N); nogc auto dot1(V)(in V lhs, in V rhs) if(isVector!V) { static if(is(V==MatrixImpl!(S,1,N),S,N)) { S ret=0; return ret; } } ```
May 01 2022
On Sunday, 1 May 2022 at 12:39:08 UTC, Elfstone wrote:Great, I'm using the constraint, until it's fixed. Will it be fixed though? The DIP that Tejas linked is from 2020!!!The DIP was postponed. I can contact the author to see if he intends to pick it up again. If not, anyone interested can take it over. And anyone can submit an alternative at any time.
May 01 2022
On Sunday, 1 May 2022 at 14:14:59 UTC, Mike Parker wrote:On Sunday, 1 May 2022 at 12:39:08 UTC, Elfstone wrote:Thanks. This breaks a lot of things. I don't know the reason behind the postponing, but who would expect one can't declare a parameter with an alias if it's a template?! Speaking of inconsistency. I'm sure there are bigger issues out there to be solved, but it's quite disencouraging if such a significant improvement(or rather fix) stays ignored. ---- I just recently started investing my spare time in D, rewriting something I wrote in C++, because the first look at D was really nice. I ran into quite a few problems and have questioned the design here and there. Fortunately (and unfortunately), this so far is the biggest issue I've run into. For now, I think I'll keep doing what I have being doing, hoping D will suit my purpose. Then I can invest more.Great, I'm using the constraint, until it's fixed. Will it be fixed though? The DIP that Tejas linked is from 2020!!!The DIP was postponed. I can contact the author to see if he intends to pick it up again. If not, anyone interested can take it over. And anyone can submit an alternative at any time.
May 01 2022
On Monday, 2 May 2022 at 00:54:40 UTC, Elfstone wrote:Thanks. This breaks a lot of things. I don't know the reason behind the postponing, but who would expect one can't declare a parameter with an alias if it's a template?! Speaking of inconsistency.At the bottom of the DIP you can find a link to the first community review round and a summary of the feedback. You'll see the DIP author decided he needed to do more work on the it. Ultimately, he decided he didn't have a deep enough understanding to complete the DIP without some research, but he was too busy to make that investment. I suggested we mark it as postponed until he could come back to it. Reviewing our conversation, he was willing to someone else taking it over. So if anyone is willing, I don't need to wait on a response from him to make that happen.I'm sure there are bigger issues out there to be solved, but it's quite disencouraging if such a significant improvement(or rather fix) stays ignored.Everyone rates issues differently. What's significant to one person won't be to another. There is much, much work to be done on shoring up holes in existing systems and solving problems the language maintainers believe to be significant, but resources are limited. So some things will inevitably be left to one side until someone picks them up. For issues that are bugs or minor enhancements, we now have Razvan Nitu and Dennis Korpel in part-time positions funded by Symmetry Investments. They manage our issues database and our pull request queues. You can always ping one of them about any particular issue that doesn't require a DIP. This has been a huge change for the better. It means issues and PRs are much less likely to stagnate. For something like your issue, which is a modification of the specification, a DIP is required. And that means either writing one or finding someone willing to write one and see it through to the end of the process. This isn't like managing bugs and pull requests. We simply don't have enough people on board to work on things like this. So it has to be done by interested parties in the community. I wouldn't expect you to take over DIP 1023 yourself since you're new to the language, but if it's important enough to you, perhaps you can find someone to champion it, given a little time. Maybe the original author would be willing to pick it up again.
May 01 2022
On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone wrote:module test; struct MatrixImpl(S, size_t M, size_t N) { } template Vector(S, size_t N) { alias Vector = MatrixImpl!(S, 1, N); } nogc S dot1(S, size_t N)(in Vector!(S, N) lhs, in Vector!(S, N) rhs) { return 0; } nogc S dot2(S, size_t N)(in MatrixImpl!(S, 1, N) lhs, in MatrixImpl!(S, 1, N) rhs) { return 0; } unittest { import std.stdio; Vector!(float, 2) a, b; dot1(a, b); // Error: none of the overloads of template `test.dot1` are callable using argument types `!()(MatrixImpl!(float, 1LU, 2LU), MatrixImpl!(float, 1LU, 2LU))` // Candidate is: `dot1(S, ulong N)(in Vector!(S, N) lhs, in Vector!(S, N) rhs)` dot2(a, b); // compiles static if (is(Vector!(float, 2) == MatrixImpl!(float, 1, 2))) { writeln("WTH"); // prints } } It's natural to declare it the way dot1 is declared, isn't it? Is this a bug? Or I simply can't assume alias works the way I thought it would. Can I work around it, without falling back to the abominable dot2?Template deduction for aliased function parameter is a very tricky argument and it's not so simple to handle in certain cases. Consider for example this code: ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce T simp( cast(MyAlias!string) 4);//Also invalid since MyAlias!string is exactly int simp!string(4);//Ok, no parameter deduction } ``` Instead to use aliases it's better (both in D and in C++) to use constraints/concepts.
May 02 2022
On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone wrote:I don't really see what your example is trying to show. This also doesn't work, and in my mind should be equivalent: ```d T simp(T)(int val) { return T.init; } int main() { simp(3);//Impossible to deduce T } ```[...]Template deduction for aliased function parameter is a very tricky argument and it's not so simple to handle in certain cases. Consider for example this code: ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce T simp( cast(MyAlias!string) 4);//Also invalid since MyAlias!string is exactly int simp!string(4);//Ok, no parameter deduction } ```
May 02 2022
On Monday, 2 May 2022 at 17:21:53 UTC, JG wrote:On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:Yeah I know, but I'm trying to show that allowing aliased templated function parameters will bring many bugs in user code, especially with aliases that alias another aliased declarations. I think using [typedefs](https://dlang.org/phobos/std_typecons.html#Typedef) and template constraints is simpler and make your code more readable too.On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone wrote:I don't really see what your example is trying to show. This also doesn't work, and in my mind should be equivalent: ```d T simp(T)(int val) { return T.init; } int main() { simp(3);//Impossible to deduce T } ```[...]Template deduction for aliased function parameter is a very tricky argument and it's not so simple to handle in certain cases. Consider for example this code: ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce T simp( cast(MyAlias!string) 4);//Also invalid since MyAlias!string is exactly int simp!string(4);//Ok, no parameter deduction } ```
May 03 2022
On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:Template deduction for aliased function parameter is a very tricky argument and it's not so simple to handle in certain cases. Consider for example this code: ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce TWhy? That's the issue. It is very possible to deduce T here. Compiler just isn't trying. The function takes an int. Doesn't take a rocket scientist to figure that one out.simp( cast(MyAlias!string) 4);//Also invalid since MyAlias!string is exactly intYes, invalid, as well it should be.simp!string(4);//Ok, no parameter deduction } ```No issue here.Instead to use aliases it's better (both in D and in C++) to use constraints/concepts.No. It *would* be better if compiler didn't play stupid here. I shouldn't have to write 50+ more lines boilerplate for what the compiler should be able to figure out. I might as well forego the templates and just write explicit overloads. At which point I would question why use templates at all.
May 02 2022
On 5/2/22 12:17, Stanislav Blinov wrote:On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:That's fine because D does not promise to solve such problems. It follows simple deduction rules.Template deduction for aliased function parameter is a very tricky argument and it's not so simple to handle in certain cases. Consider for example this code: ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce TWhy? That's the issue. It is very possible to deduce T here. Compiler just isn't trying.The function takes an int.How would the solution be? Wouldn't the compiler have to parse all accessible template bodies to figure out which ones fit? Imagine the following two other templates: template YourAlias(T) { alias YourAlias = int; // Is it this one? } template HerAlias(T) { // ... alias HerAlias = HisAlias!SomeNameInThisScope; // Or thi? } The compiler would have to solve this problem by digging into HisAlias's SomeNameInThisScope instantiation as well. As far as know, the D language does not work that way. Prolog and friends perhaps?Doesn't take a rocket scientist to figure that one out.I think this is one of those cases where it is easier for a human. Although, I think I would have difficulty if there were more than one template parameter.I might as well forego the templates and just write explicit overloads. At which point I would question why use templates at all.Templates allow single implementations to work for many types, manifest constants, aliases, etc. I wouldn't want to write (or mix-in?) sort() for MyType. Templates are wonderful and their implementation in D is refreshing. Ali
May 02 2022
On Monday, 2 May 2022 at 20:08:48 UTC, Ali Çehreli wrote:On 5/2/22 12:17, Stanislav Blinov wrote:Words, dear guru. Words have a meaning. It is very possible to deduce here (note the premise). D just isn't trying. That's what I said. You can say "it doesn't promise". Doesn't exactly change the meaning, does it? :)On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:trickyTemplate deduction for aliased function parameter is a veryConsiderargument and it's not so simple to handle in certain cases.Compilerfor example this code: ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce TWhy? That's the issue. It is very possible to deduce T here.just isn't trying.That's fine because D does not promise to solve such problems. It follows simple deduction rules.Err... yes? That's what it *is* doing already, for all templates.The function takes an int.How would the solution be? Wouldn't the compiler have to parse all accessible template bodies to figure out which ones fit?Imagine the following two other templates: template YourAlias(T) { alias YourAlias = int; // Is it this one? } template HerAlias(T) { // ... alias HerAlias = HisAlias!SomeNameInThisScope; // Or thi? }No. HerAlias and YourAlias are different symbols.The compiler would have to solve this problem by digging into HisAlias's SomeNameInThisScope instantiation as well. As far as know, the D language does not work that way. Prolog and friends perhaps?Nope. MyAlias is an alias. A template alias, but an alias nonetheless. It should be resolved prior to trying the overloads.That's what we have compilers for.Doesn't take a rocket scientist to figure that one out.I think this is one of those cases where it is easier for a human. Although, I think I would have difficulty if there were more than one template parameter.It is, until is isn't. Question du jeour is one of those.I might as well forego the templates and just write explicit overloads. At which point I wouldquestion why usetemplates at all.Templates allow single implementations to work for many types, manifest constants, aliases, etc. I wouldn't want to write (or mix-in?) sort() for MyType. Templates are wonderful and their implementation in D is refreshing.
May 02 2022
On 5/2/22 13:36, Stanislav Blinov wrote:What I mean is, problem solving the way you expect is not in D's charter.That's fine because D does not promise to solve such problems. It follows simple deduction rules.Words, dear guru. Words have a meaning. It is very possible to deduce here (note the premise). D just isn't trying. That's what I said. You can say "it doesn't promise". Doesn't exactly change the meaning, does it? :)No, the compiler does not parse all templates. Only the ones that needs instantiation.Err... yes? That's what it *is* doing already, for all templates.The function takes an int.How would the solution be? Wouldn't the compiler have to parse all accessible template bodies to figure out which ones fit?You are right. I confused myself there but it is not that different when we stay with MyAlias alone. I am changing 'int' to YourAlias!T: template MyAlias(T){ alias MyAlias = YourAlias!T; } Do you still expect the compiler to dig into YourAlias and solve a problem to see whether YourAlias can be the same as aliasing 'int'? Would that enough trying by the compiler? If not, where should the compiler stop? In any case, that is not what D is. That's what I meant. Not being even a junior guru, I don't know what categories of programming languages do that. Declarative? Logic? All I know is D is not among them.Imagine the following two other templates: template YourAlias(T) { alias YourAlias = int; // Is it this one? } template HerAlias(T) { // ... alias HerAlias = HisAlias!SomeNameInThisScope; // Or thi? }No. HerAlias and YourAlias are different symbols.Not going to happen.The compiler would have to solve this problem by digging into HisAlias's SomeNameInThisScope instantiation as well. As far as know, the D language does not work that way. Prolog and friends perhaps?Nope. MyAlias is an alias. A template alias, but an alias nonetheless. It should be resolved prior to trying the overloads.We also have NP-completeness.That's what we have compilers for.Doesn't take a rocket scientist to figure that one out.I think this is one of those cases where it is easier for a human. Although, I think I would have difficulty if there were more than one template parameter.No, the question is whether D is in a category of programming languages that it isn't. AliIt is, until is isn't. Question du jeour is one of those.I might as well forego the templates and just write explicit overloads. At which point I wouldquestion why usetemplates at all.Templates allow single implementations to work for many types, manifest constants, aliases, etc. I wouldn't want to write (or mix-in?) sort() for MyType. Templates are wonderful and their implementation in D is refreshing.
May 03 2022
On Tuesday, 3 May 2022 at 15:41:08 UTC, Ali Çehreli wrote:We also have NP-completeness.Ok, so C++ has similar limitations when you have a template with an unknown parameter in a function parameter, but is this because it would be NPC? Also, do we know that it cannot be resolved for the typical case in reasonable time? Maybe one can add constraints and heuristics that keeps it reasonable?No, the question is whether D is in a category of programming languages that it isn't.Fair enough, but type unification needs to be done differently anyway, just to support aliases being recognized in function calls. Why not look at what is possible before going there? Certainly, having something more expressive than C++ would not be a bad thing?
May 03 2022
On 02.05.22 21:17, Stanislav Blinov wrote:On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:[...]I take it your answer is that T must be int. But that's nonsense. MyAlias maps all types to int. It's not a bijection, you can't turn it around.```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce TWhy? That's the issue. It is very possible to deduce T here. Compiler just isn't trying. The function takes an int. Doesn't take a rocket scientist to figure that one out.
May 02 2022
On Monday, 2 May 2022 at 20:16:04 UTC, ag0aep6g wrote:On 02.05.22 21:17, Stanislav Blinov wrote:That's not my answer. And it is nonsense, because my answer is - what T is irrelevant, MyAlias maps *all* types to int. Therefore `simp` takes an int, which is what the caller is passing.On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:[...]I take it your answer is that T must be int. But that's nonsense. MyAlias maps all types to int. It's not a bijection, you can't turn it around.```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce TWhy? That's the issue. It is very possible to deduce T here. Compiler just isn't trying. The function takes an int. Doesn't take a rocket scientist to figure that one out.
May 02 2022
On 02.05.22 22:47, Stanislav Blinov wrote:On Monday, 2 May 2022 at 20:16:04 UTC, ag0aep6g wrote:[...]On 02.05.22 21:17, Stanislav Blinov wrote:On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:[...]```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce TThat's not my answer. And it is nonsense, because my answer is - what T is irrelevant, MyAlias maps *all* types to int. Therefore `simp` takes an int, which is what the caller is passing.And what does it return?
May 02 2022
On Monday, 2 May 2022 at 22:01:51 UTC, ag0aep6g wrote:On 02.05.22 22:47, Stanislav Blinov wrote:Perhaps one way could be to assume that the parameter passed is of type `aliasTemplate!typeOfVar` and see if it helps make sense of the invocation? This would only be done if the parameter's type doesn't directly match the required type nor it is implicitly convertible to it(which can be further constrained by... constraints...) For example, here: ```d template MyAlias(T){ alias MyAlias = int; } // Please note that I changed code, since this is the only way to get the type with which the template parameter was initialized U simp(T:MyAlias!U, U)(auto ref T val){ return U.init; } int main(){ simp(3); // val is inferred to be of type MyAlias!int simp(”4”); // val is of type MyAlias!string simp!string([4,0]); val is of type MyAlias!(int[]) MyAlias!float d =45; simp(d); // val is inferred to be of type MyAlias!(MyAlias!float) // hopefully though the second MyAlias doesn't have to exist and it can just assume the type to be int } ```On Monday, 2 May 2022 at 20:16:04 UTC, ag0aep6g wrote:[...]On 02.05.22 21:17, Stanislav Blinov wrote:On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:[...]```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce TThat's not my answer. And it is nonsense, because my answer is - what T is irrelevant, MyAlias maps *all* types to int. Therefore `simp` takes an int, which is what the caller is passing.And what does it return?
May 02 2022
On Tuesday, 3 May 2022 at 00:38:34 UTC, Tejas wrote:On Monday, 2 May 2022 at 22:01:51 UTC, ag0aep6g wrote:Edit: correcting the code ```d template MyAlias(T){ alias MyAlias = int; } // Please note that I changed code, since this is the only way to get the type with which the template parameter was initialized U simp(T:MyAlias!U, U)(auto ref T val){ return U.init; } int main(){ simp(3); // val is inferred to be of type MyAlias!int simp(”4”); // val is of type MyAlias!string simp([4,0]);// val is of type MyAlias!(int[]) MyAlias!float d =45; simp(d); // val is inferred to be of type MyAlias!(MyAlias!float) // hopefully though the second MyAlias doesn't have to exist and it can just assume the type to be int }On 02.05.22 22:47, Stanislav Blinov wrote:Perhaps one way could be to assume that the parameter passed is of type `aliasTemplate!typeOfVar` and see if it helps make sense of the invocation? This would only be done if the parameter's type doesn't directly match the required type nor it is implicitly convertible to it(which can be further constrained by... constraints...) For example, here: ```d template MyAlias(T){ alias MyAlias = int; } // Please note that I changed code, since this is the only way to get the type with which the template parameter was initialized U simp(T:MyAlias!U, U)(auto ref T val){ return U.init; } int main(){ simp(3); // val is inferred to be of type MyAlias!int simp(”4”); // val is of type MyAlias!string simp!string([4,0]); val is of type MyAlias!(int[]) MyAlias!float d =45; simp(d); // val is inferred to be of type MyAlias!(MyAlias!float) // hopefully though the second MyAlias doesn't have to exist and it can just assume the type to be int } ```On Monday, 2 May 2022 at 20:16:04 UTC, ag0aep6g wrote:[...]On 02.05.22 21:17, Stanislav Blinov wrote:On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:[...]```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce TThat's not my answer. And it is nonsense, because my answer is - what T is irrelevant, MyAlias maps *all* types to int. Therefore `simp` takes an int, which is what the caller is passing.And what does it return?
May 02 2022
On Monday, 2 May 2022 at 19:17:19 UTC, Stanislav Blinov wrote:On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:Maybe I am being silly, but it isn't possible to determine T here. Independent of what T is the input parameter would be an int (which the compiler can't see but we can) but the output depends on T which can't be deduced.Template deduction for aliased function parameter is a very tricky argument and it's not so simple to handle in certain cases. Consider for example this code: ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce TWhy? That's the issue. It is very possible to deduce T here. Compiler just isn't trying. The function takes an int. Doesn't take a rocket scientist to figure that one out.
May 02 2022
On Monday, 2 May 2022 at 19:17:19 UTC, Stanislav Blinov wrote:On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:No, an alias is not a type and it'll be immediately substitutedwith the aliased symbol. You should use [typedefs](https://dlang.org/phobos/std_typecons.html#Typedef) in order to create a different type.Template deduction for aliased function parameter is a very tricky argument and it's not so simple to handle in certain cases. Consider for example this code: ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce TWhy? That's the issue. It is very possible to deduce T here. Compiler just isn't trying. The function takes an int. Doesn't take a rocket scientist to figure that one out.
May 03 2022
On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone wrote:Yeah, I understand some cases are impossible, and to be avoided. I believe your example is also impossible in C++, but it's better the compiler do its job when it's totally possible - needless to say, C++ compilers can deduce my _dot_. Constraints/Concepts are useful, but what's needed here is a literal _alias_. There's no ambiguity, no extra template parameters introduced in the declaration.[...]Template deduction for aliased function parameter is a very tricky argument and it's not so simple to handle in certain cases. Consider for example this code: ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce T simp( cast(MyAlias!string) 4);//Also invalid since MyAlias!string is exactly int simp!string(4);//Ok, no parameter deduction } ``` Instead to use aliases it's better (both in D and in C++) to use constraints/concepts.
May 02 2022
On Tuesday, 3 May 2022 at 06:20:53 UTC, Elfstone wrote:Yeah, I understand some cases are impossible, and to be avoided. I believe your example is also impossible in C++, but it's better the compiler do its job when it's totally possible - needless to say, C++ compilers can deduce my _dot_. Constraints/Concepts are useful, but what's needed here is a literal _alias_. There's no ambiguity, no extra template parameters introduced in the declaration.I haven't read all of the posts in this thread, but D in general doesn't do proper type unification so template composition in D is not as useful as in C++. It is discussed here: https://forum.dlang.org/post/rt26mu$2c6q$1 digitalmars.com As you see, someone will have to write a DIP to fix this bug, as the language authors don't consider it a bug, but an enhancement. I've never got around to do it myself, but if you or someone else write the DIP, then I would like to help out with the wording if needed.
May 03 2022
On Tuesday, 3 May 2022 at 07:11:48 UTC, Ola Fosheim Grøstad wrote:As you see, someone will have to write a DIP to fix this bug, as the language authors don't consider it a bug, but an enhancement.I don't believe those two words are mutually exclusive. It can be a bug __and__ an enhancement. But to deny that this is a bug is just being lazy.
May 04 2022
On Wednesday, 4 May 2022 at 10:15:18 UTC, bauss wrote:It can be a bug __and__ an enhancement.Alright, but we need a DIP to get the enhancement which can be in. :-) I don't think anything will improve without one. I would assume that C++ template resolution is O(N), so I am not as pessimistic as Ali, but I could be wrong.
May 04 2022