www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Parameters declared as the alias of a template won't accept the

reply Elfstone <elfstone yeah.net> writes:
     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
next sibling parent reply Tejas <notrealemail gmail.com> writes:
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
parent reply Elfstone <elfstone yeah.net> writes:
On Sunday, 1 May 2022 at 06:42:26 UTC, Tejas wrote:
 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
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
parent reply JG <someone somewhere.com> writes:
On Sunday, 1 May 2022 at 07:59:57 UTC, Elfstone wrote:
 On Sunday, 1 May 2022 at 06:42:26 UTC, Tejas wrote:
 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
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.
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"); } ```
May 01 2022
parent reply JG <someone somewhere.com> writes:
On Sunday, 1 May 2022 at 11:34:49 UTC, JG wrote:
 On Sunday, 1 May 2022 at 07:59:57 UTC, Elfstone wrote:
 On Sunday, 1 May 2022 at 06:42:26 UTC, Tejas 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.
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"); } ```
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
parent reply Elfstone <elfstone yeah.net> writes:
On Sunday, 1 May 2022 at 11:37:28 UTC, JG wrote:
 On Sunday, 1 May 2022 at 11:34:49 UTC, JG 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; } } ```
Great, I'm using the constraint, until it's fixed. Will it be fixed though? The DIP that Tejas linked is from 2020!!!
May 01 2022
parent reply Mike Parker <aldacron gmail.com> writes:
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
parent reply Elfstone <elfstone yeah.net> writes:
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:
 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.
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.
May 01 2022
parent Mike Parker <aldacron gmail.com> writes:
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
prev sibling parent reply Loara <loara noreply.com> writes:
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
next sibling parent reply JG <someone somewhere.com> writes:
On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:
 On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone 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 T simp( cast(MyAlias!string) 4);//Also invalid since MyAlias!string is exactly int simp!string(4);//Ok, no parameter deduction } ```
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 } ```
May 02 2022
parent Loara <loara noreply.com> writes:
On Monday, 2 May 2022 at 17:21:53 UTC, JG wrote:
 On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:
 On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone 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 T simp( cast(MyAlias!string) 4);//Also invalid since MyAlias!string is exactly int simp!string(4);//Ok, no parameter deduction } ```
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 } ```
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.
May 03 2022
prev sibling next sibling parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
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 T
Why? 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 int
Yes, 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
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 5/2/22 12:17, Stanislav Blinov wrote:
 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 T
Why? That's the issue. It is very possible to deduce T here. Compiler just isn't trying.
That's fine because D does not promise to solve such problems. It follows simple deduction rules.
 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
parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Monday, 2 May 2022 at 20:08:48 UTC, Ali Çehreli wrote:
 On 5/2/22 12:17, Stanislav Blinov wrote:
 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 T
Why? That's the issue. It is very possible to deduce T here.
Compiler
 just isn't trying.
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? :)
 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?
Err... yes? That's what it *is* doing already, for all templates.
 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.
 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.
That's what we have compilers for.
 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.
It is, until is isn't. Question du jeour is one of those.
May 02 2022
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
	On 5/2/22 13:36, Stanislav Blinov wrote:

 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? :)
What I mean is, problem solving the way you expect is not in D's charter.
 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?
Err... yes? That's what it *is* doing already, for all templates.
No, the compiler does not parse all templates. Only the ones that needs instantiation.
 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.
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.
 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.
Not going to happen.
 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.
That's what we have compilers for.
We also have NP-completeness.
 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.
It is, until is isn't. Question du jeour is one of those.
No, the question is whether D is in a category of programming languages that it isn't. Ali
May 03 2022
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
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
prev sibling next sibling parent reply ag0aep6g <anonymous example.com> writes:
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 T
Why? 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.
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.
May 02 2022
parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
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 T
Why? 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.
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.
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.
May 02 2022
parent reply ag0aep6g <anonymous example.com> writes:
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 T
[...]
 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.
And what does it return?
May 02 2022
parent reply Tejas <notrealemail gmail.com> writes:
On Monday, 2 May 2022 at 22:01:51 UTC, ag0aep6g wrote:
 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 T
[...]
 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.
And what does it return?
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 } ```
May 02 2022
parent Tejas <notrealemail gmail.com> writes:
On Tuesday, 3 May 2022 at 00:38:34 UTC, Tejas wrote:
 On Monday, 2 May 2022 at 22:01:51 UTC, ag0aep6g wrote:
 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 T
[...]
 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.
And what does it return?
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 } ```
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 }
May 02 2022
prev sibling next sibling parent JG <someone somewhere.com> writes:
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:

 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
Why? 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.
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.
May 02 2022
prev sibling parent Loara <loara noreply.com> writes:
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:

 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
Why? 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.
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.
May 03 2022
prev sibling parent reply Elfstone <elfstone yeah.net> writes:
On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote:
 On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone 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 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.
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.
May 02 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
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
parent reply bauss <jj_1337 live.dk> writes:
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
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
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