www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 1528] New: shouldn't templates conflict with templates?

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528

           Summary: shouldn't templates conflict with templates?
           Product: D
           Version: unspecified
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: trivial
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: davidl 126.com


int[char] v;
char m;
int d;

template toString (U,C,T:U[C])
{
        char[] toString(U m,C c, T t) { return ""; }
}
char[] toString(int k){return "";}   

The confliction can actually be detected till the last moment of instantiation.
I don't see why we prevent it at the moment.


-- 
Sep 22 2007
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


wbaxter gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|shouldn't templates conflict|templates should not
                   |with templates?             |conflict with non-templates





The ability to do this sort of overloading is scheduled to be added to D2.0,
according to the notes from the Walter/Andrei talk at the D conference.


-- 
Sep 22 2007
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|spec                        |
                 CC|                            |clugdbug yahoo.com.au
           Severity|trivial                     |enhancement


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Sep 22 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei metalanguage.com



*** Issue 7134 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 24 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |rejects-valid
                 CC|                            |yebblies gmail.com
           Platform|x86                         |All
            Summary|[tdpl] templates should not |[tdpl] overloading template
                   |conflict with non-templates |and non-template functions
         OS/Version|Windows                     |All
           Severity|enhancement                 |major



From Andrei's comment in 7134:

This TDPL code does not compile:

class A {
   // Non-overridable method
   A opBinary(string op)(A rhs) {
      // Forward to an overridable function
      return opBinary(op, rhs);
   }
   // Overridable method, dispatch string at runtime
   A opBinary(string op, A rhs) {
      switch (op) {
         case "+":
            break;
         case "-":
            break;
      }
   }
}

Overloading template and non-template functions must be implemented.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 24 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




09:15:52 PST ---
Thanks for consolidating!

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 24 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Andrej Mitrovic <andrej.mitrovich gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dsimcha yahoo.com



18:22:11 PST ---
*** Issue 2972 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 21 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Simen Kjaeraas <simen.kjaras gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simen.kjaras gmail.com



PDT ---
This bug causes problems with  disabled default constructors.

Given:

struct Foo {
     disable this();
    this( T )( T a ) {
    }
}

This bug triggers.

Given instead:

struct Bar {
     disable this( )( );
    this( T )( T a ) {
    }
}

The default constructor is not disabled.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Aug 25 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Jonathan M Davis <jmdavisProg gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jmdavisProg gmx.com



PDT ---
 This bug causes problems with  disabled default constructors.
I don't think that this bug has anything to do with it. And I wouldn't expect disable this()(); to work anyway, because the function that you're trying to disable doesn't exist. It would have to be instantiatied to exist, and it's not possible to call a default constructor on a struct, since they're not legal in the first place, so it can't be instantiated. disable this()(); should probably result in an error. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 25 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




PDT ---

 This bug causes problems with  disabled default constructors.
disable this() does work in some cases: struct Foo { disable this( ); } struct Bar { Foo f; this( int n ) { // Error: constructor Bar.this field f must be initialized in constructor } } void main( ) { Foo f; // Error: variable main.d initializer required for type Foo } However, if you need a templated constructor, this goes out the window, for the reasons outlined above.
 I don't think that this bug has anything to do with it.
Yes and no. The problems of disable this are exacerbated by this bug.
 And I wouldn't expect  disable this()(); to work anyway, because the function
 that you're trying to disable doesn't exist. It would have to be instantiatied
 to exist, and it's not possible to call a default constructor on a struct,
 since they're not legal in the first place, so it can't be instantiated.
  disable this()(); should probably result in an error.
Nor would I, but when faced with the error that templated and non-templated functions cannot form an overload set together, that is the logical thing to try, and it doesn't work either. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 25 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull



https://github.com/D-Programming-Language/dmd/pull/1409

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|pull                        |



---

 https://github.com/D-Programming-Language/dmd/pull/1409
By implementing it, I found some corner cases. How should these behave? int f1(int a, double=10) { return 1; } int f1(int a, string="") { return 2; } int f2(T:int)(T b, double=10) { return 1; } int f2(T:int)(T b, string="") { return 2; } // vs deduced parameter int f3(int a) { return 1; } int f3(T)(T b) { return 2; } // vs specialized parameter int f4(int a) { return 1; } int f4(T:int)(T b) { return 2; } // vs deduced parameter + template constraint (1) int f5(int a) { return 1; } int f5(T)(T b) if (is(T == int)) { return 2; } // vs deduced parameter + template constraint (2) int f6(int a) { return 1; } int f6(T)(T b) if (is(T : int)) { return 2; } void main() { f1(1); // ambiguous error f1(1L); // ambiguous error f2(1); // ambiguous error f2(1L); // ambiguous error f3(1); // ? f3(1L); // ? f4(1); // ? f4(1L); // ? f5(1); // ? f5(1L); // ? f6(1); // ? f6(1L); // ? } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




21:54:47 PST ---

     f3(1);  // 1
     f3(1L); // 2
 
     f4(1);  // ambiguous
     f4(1L); // ambiguous
 
     f5(1);  // 1
     f5(1L); // 1
 
     f6(1);  // 1
     f6(1L); // 2
 }
The more specialized overload always wins. The constraint is not considered when evaluating which is "more specialized". (Because in general we cannot evaluate that.) The constraint only determines if an overload is to be considered - it does not determine ordering. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




---

 The more specialized overload always wins.
 
 The constraint is not considered when evaluating which is "more specialized".
 (Because in general we cannot evaluate that.) The constraint only determines if
 an overload is to be considered - it does not determine ordering.
Thanks for quickly answer. So, the resolution result of f5 and f6 should be same as f3, because they are identical when hide their constraints. Right? But, there is still questionable. How to calculate "The more specialized overload" between function template and non-template one? For example, try to consider case for f3(1). That is: 1. Normal function version f3(int) will match exactly to one int argument. 2. Function template version will deduce T <- int, and then instantiated function f3!(int) == void f3(int) will match _exactly_ to one int argument. But, in general, template version is less specialized than non-template version. So, there is something necessary for ordering. --- Consider one another case for f4(1L). That is: 1. Normal function will match to one long argument with conversion (MATCHconvert). 2. Function template version will deduce T <- long and then instantiated function f4!long will match exactly to one long argument. Which is specialized? In general, template version would be intended to pick up non-exact matching for generic cases. But, as far as I infer from current dmd implementation, f4(1L) will be ambiguous (template type parameter deduction without specialization always be MATCHconvert). Therefore, I'd ask question again to Walter: how does above cases behave? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


timon.gehr gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr gmx.ch




 ...
 
 Therefore, I'd ask question again to Walter: how does above cases behave?
I have implemented it in accordance with TDPL, and the following behaviour results: int f1(int a, double=10) { return 1; } int f1(int a, string="") { return 2; } int f2(T:int)(T b, double=10) { return 1; } int f2(T:int)(T b, string="") { return 2; } // vs deduced parameter int f3(int a) { return 1; } int f3(T)(T b) { return 2; } // vs specialized parameter int f4(int a) { return 1; } int f4(T:int)(T b) { return 2; } // vs deduced parameter + template constraint (1) int f5(int a) { return 1; } int f5(T)(T b) if (is(T == int)) { return 2; } // vs deduced parameter + template constraint (2) int f6(int a) { return 1; } int f6(T)(T b) if (is(T : int)) { return 2; } void main(){ f1(1); // error: ambiguous f1(1L); // error: ambiguous f2(1); // error: ambiguous f2(1L); // error: no match static assert(f3(1)==1); static assert(f3(1L)==2); static assert(f4(1)==1); static assert(f4(1L)==1); static assert(f5(1)==1); static assert(f5(1L)==1); static assert(f6(1)==1); static assert(f6(1L)==1); } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 25 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


monarchdodra gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra gmail.com




 I have implemented it in accordance with TDPL, and the following behaviour
 results:
 
 // vs deduced parameter + template constraint (2)
 int f6(int a) { return 1; }
 int f6(T)(T b) if (is(T : int)) { return 2; }
 
 void main(){
     static assert(f6(1)==1);
     static assert(f6(1L)==1);
 }
How does that work though, because here, you statically know that 1L will fit in your int. But what about: static assert(f6(1L) == 1); static assert(f6(ulong.max) == 2); // (a) ??? ulong ul = runtime(); static assert(f6(ul) == 2); // (b) ??? How would these resolve? I am not really comfortable with the fact that a call can statically resolve to two different functions depending on the static information of the *value* of a parameter: int f7(ubyte a) { return 1; } int f7(T)(T b) if (is(T : int)) { return 2; } void main(){ static assert(f6(200u)==1); //Calls first static assert(f6(400u)==2); //Calls second (!?) //Run-time variable with TDPL-like range knowledge uint a = 400; static assert(f6(a) == 2); //Calls second ? a = 200; static assert(f6(a) == 1); //But now calls first !? } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 27 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528





 ...
 
 static assert(f6(1L) == 1);
 static assert(f6(ulong.max) == 2); // (a) ???
 
No match.
 ulong ul = runtime();
 static assert(f6(ul) == 2);        // (b) ???
 
No match.
 How would these resolve?
 
 I am not really comfortable with the fact that a call can statically resolve to
 two different functions depending on the static information of the *value* of a
 parameter:
 
Well, that is how the language is specified. int f8(byte){ return 1; } int f8(long){ return 2; } void main(){ static assert(f8(1)==1); // calls first static assert(f8(256)==2); // calls second int x=1; f8(x); // calls second }
 int f7(ubyte a) { return 1; }
 int f7(T)(T b) if (is(T : int)) { return 2; }
 
 void main(){
     static assert(f6(200u)==1); //Calls first
No, calls second.
     static assert(f6(400u)==2); //Calls second (!?)
 
Yes.
     //Run-time variable with TDPL-like range knowledge
     uint a = 400;
Knowledge lost here.
     static assert(f6(a) == 2); //Calls second  ?
     a = 200;
Ditto.
     static assert(f6(a) == 1); //But now calls first !?
 }
-- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 27 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




---

 // vs specialized parameter
 int f4(int a) { return 1; }
 int f4(T:int)(T b) { return 2; }
     static assert(f4(1)==1);
Just only this is wrong. f4(T:int) is specialized to int argument, so f4(1) could match both normal function version and template version *with the same extent*. Then it will be ambiguous.
     static assert(f4(1L)==1);
Ok. f4(T:int) cannot instantiate with T==long, so first version will be called.

 ...
 
 static assert(f6(1L) == 1);
 static assert(f6(ulong.max) == 2); // (a) ???
 
No match.
 ulong ul = runtime();
 static assert(f6(ul) == 2);        // (b) ???
 
No match.
Both (a) and (b) should be "no match", but with my experimental change, (a) wrongly matches to int. I found an another bug in there, and filed it as bug 9617. Current test case results with my pull request: https://github.com/D-Programming-Language/dmd/pull/1409 is: -------- int f1(int a, double=10) { return 1; } int f1(int a, string="") { return 2; } int f2(T:int)(T b, double=10) { return 1; } int f2(T:int)(T b, string="") { return 2; } // vs deduced parameter int f3(int a) { return 1; } int f3(T)(T b) { return 2; } // vs specialized parameter int f4(int a) { return 1; } int f4(T:int)(T b) { return 2; } // vs deduced parameter + template constraint (1) int f5(int a) { return 1; } int f5(T)(T b) if (is(T == int)) { return 2; } // vs deduced parameter + template constraint (2) int f6(int a) { return 1; } int f6(T)(T b) if (is(T : int)) { return 2; } // vs nallowing conversion int f7(ubyte a) { return 1; } int f7(T)(T b) if (is(T : int)) { return 2; } void main() { static assert(!__traits(compiles, f1(1))); // ambiguous static assert(!__traits(compiles, f1(1L))); // ambiguous static assert(!__traits(compiles, f2(1))); // ambiguous static assert(!__traits(compiles, f2(1L))); // no match assert(f3(1) == 1); assert(f3(1L) == 2); static assert(!__traits(compiles, f4(1))); assert(f4(1L) == 1); assert(f5(1) == 1); assert(f5(1L) == 1); assert(f6(1) == 1); assert(f6(1L) == 1); static assert(!__traits(compiles, f6(ulong.max))); // no match // needs to fix bug 9617 ulong ulval = 1; static assert(!__traits(compiles, f6(ulval))); // no match assert(f7(200u) == 2); assert(f7(400u) == 2); uint uival = 400; // TDPL-like range knowledge lost here. assert(f7(uival) == 2); a = 200; // Ditto. assert(f7(uival) == 2); } -------- I welcome more complicated test case. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 28 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Martin Nowak <code dawg.eu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |code dawg.eu



 template type parameter deduction without specialization always be MATCHconvert
AFAIK this is a kludgy implementation detail to make specialization work. The last time we worked on that we concluded (with Daniel Murphy?) that there should be an additional level between convert and exact. I don't remember the details right now, but I'll try to find the relevant discussion. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528





 template type parameter deduction without specialization always be MATCHconvert
AFAIK this is a kludgy implementation detail
It is a bug.
 to make specialization work.
Why wouldn't they work otherwise?
 The
 last time we worked on that we concluded (with Daniel Murphy?) that there
 should be an additional level between convert and exact. I don't remember the
 details right now, but I'll try to find the relevant discussion.
There already is a level between them (conversion to const.) Anyway, I do not see why another level would be required, or even helpful in any way. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




---

 template type parameter deduction without specialization always be MATCHconvert
AFAIK this is a kludgy implementation detail to make specialization work. The last time we worked on that we concluded (with Daniel Murphy?) that there should be an additional level between convert and exact. I don't remember the details right now, but I'll try to find the relevant discussion.
Are you saying about MATCHdeduced? I had seen the Daniel Murphy's pull request somewhere, but it is completely unnecessary. In IFTI, the match level for template arguments and for function arguments are distinguished. The former is prior than the latter, so there is 3 * 3 + 1 match level in IFTI. For tiargs: exact or const or convert (3) For funargs: exact or const or convert (* 3) noatch (+ 1) During implementation, I found that the two matching levels had not be separated correctly (the bug was in TemplateDeclaration::deduceFunctionTemplateMatch). After fixing the bug, I can believe that MATCHdeduced is not need anymore. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528






 ...
 
 In IFTI, the match level for template arguments and for function arguments are
 distinguished. The former is prior than the latter, so there is 3 * 3 + 1 match
 level in IFTI.
 
   For tiargs: exact or const or convert  (3)
   For funargs: exact or const or convert  (* 3)
   noatch (+ 1)
 ...
It can be seen that way. They are ordered from worst to best like this: no match ifti convert function convert ifti const function const ifti exact function exact -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




---



 ...
 
 In IFTI, the match level for template arguments and for function arguments are
 distinguished. The former is prior than the latter, so there is 3 * 3 + 1 match
 level in IFTI.
 
   For tiargs: exact or const or convert  (3)
   For funargs: exact or const or convert  (* 3)
   noatch (+ 1)
 ...
It can be seen that way. They are ordered from worst to best like this:
More precisely: MATCHnomatch tiargs:MATCHconvert / funarg:MATCHconvert tiargs:MATCHconvert / funarg:MATCHconst tiargs:MATCHconvert / funarg:MATCHexact tiargs:MATCHconst / funarg:MATCHconvert tiargs:MATCHconst / funarg:MATCHconst tiargs:MATCHconst / funarg:MATCHexact tiargs:MATCHexact / funarg:MATCHconvert tiargs:MATCHexact / funarg:MATCHconst tiargs:MATCHexact / funarg:MATCHexact Additionally, when comparing normal function and template function matching, tiargs MATCH level is treated as equal to funargs level. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528








 ...
 
 In IFTI, the match level for template arguments and for function arguments are
 distinguished. The former is prior than the latter, so there is 3 * 3 + 1 match
 level in IFTI.
 
   For tiargs: exact or const or convert  (3)
   For funargs: exact or const or convert  (* 3)
   noatch (+ 1)
 ...
It can be seen that way. They are ordered from worst to best like this:
More precisely: MATCHnomatch tiargs:MATCHconvert / funarg:MATCHconvert tiargs:MATCHconvert / funarg:MATCHconst tiargs:MATCHconvert / funarg:MATCHexact tiargs:MATCHconst / funarg:MATCHconvert tiargs:MATCHconst / funarg:MATCHconst tiargs:MATCHconst / funarg:MATCHexact tiargs:MATCHexact / funarg:MATCHconvert tiargs:MATCHexact / funarg:MATCHconst tiargs:MATCHexact / funarg:MATCHexact Additionally, when comparing normal function and template function matching, tiargs MATCH level is treated as equal to funargs level.
Ah, now I see what you mean. You are matching foo!tiargs(funargs). I was talking about resolving template vs. non-template overloads in the foo(funargs) setting. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




---

 Ah, now I see what you mean. You are matching foo!tiargs(funargs).
 
 I was talking about resolving template vs. non-template overloads in the
 foo(funargs) setting.
I'm talking about both. You can think type parameters deduction and function arguments matching separately. For example: void foo(T)(T) {} void foo(T:int)(T) {} With first overload version, Phase 1: T is deduced to int. ==> MATCHconvert. Phase 2: 1 matches T (==already deduced to int). ==> MATCHexact. With second overload version, Phase 1: T is deduced to int and is specialized to int. ==> MATCHexact. Phase 2: 1 matches T (==already deduced to int). ==> MATCHexact. Finally, foo(T)(T) is less specialized than foo(T:int)(T). I explain more complicated case. void bar(int, int) {} void bar(T)(T, int) {} bar(1, 1L); With first overload version, Phase 1: normal function is treated as having empty template parameter list, so matching is always exact ==> MATCHexact Phase 2: int <- 1 == MATCHexact, int <- 1L == MATCHconvert. ==> MATCHconvert With second overload version, Phase 1: T <- typeof(int). ==> MATCHconvert Phase 2: T <- 1 == MATCHexact, int <- 1L == MATCHconvert ==> MATCHconvert From the comparison of Phase 1 result, bar(int, int) is more specialized than bar(T)(T, int) for function arguments (1, 1L). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528






I think this rule is problematic for the function vs. deduced parameter case.

// vs deduced parameter
int f3(int a) { return 1; }
int f3(T)(T b) { return 2; }
f3(1L);

With first overload version,
Phase 1: normal function is treated as having empty template parameter list, so
         matching is always exact  ==> MATCHexact
Phase 2: int <- 1L == MATCHconvert ==> MATCHconvert

With second overload version,
Phase 1: T <- typeof(1L) = long    ==> MATCHconvert
Phase 2: T <- 1L == MATCHexact     ==> MATCHexact

- the current implementation in the pull request chooses

  with the function template

https://github.com/9rnsr/dmd/blob/b141e29e29b1ec43873c7e0374d27d3fbbae8085/test/runnable/overload.d#L216
https://github.com/9rnsr/dmd/blob/b141e29e29b1ec43873c7e0374d27d3fbbae8085/test/runnable/overload.d#L279

- C++ chooses the function template

- For me it's counterintuitive to call with conversion when an exact
  match can be instantiated. Even an ambiguous error seems more reasonable to
me.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 14 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




I find the C++ rule pretty plausible.

 In most cases a function template behaves just like a normal function when
 considering overload resolution. The template argument deduction is
 applied, if it succeeds, the function is added to the candidates set. Such
 a function is handled like any other function, except when two viable
 functions are equally good, the non-template one is selected. In case both
 are a specialisation of a function template, partial ordering rules are
 applied. The partial ordering rules are out of the scope of this article.
http://accu.org/index.php/journals/268#d0e340 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 14 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




---


 
 I think this rule is problematic for the function vs. deduced parameter case.
 
 // vs deduced parameter
 int f3(int a) { return 1; }
 int f3(T)(T b) { return 2; }
 f3(1L);
 
 With first overload version,
 Phase 1: normal function is treated as having empty template parameter list, so
          matching is always exact  ==> MATCHexact
 Phase 2: int <- 1L == MATCHconvert ==> MATCHconvert
 
 With second overload version,
 Phase 1: T <- typeof(1L) = long    ==> MATCHconvert
 Phase 2: T <- 1L == MATCHexact     ==> MATCHexact
 
 - the current implementation in the pull request chooses

   with the function template
 
 https://github.com/9rnsr/dmd/blob/b141e29e29b1ec43873c7e0374d27d3fbbae8085/test/runnable/overload.d#L216
 https://github.com/9rnsr/dmd/blob/b141e29e29b1ec43873c7e0374d27d3fbbae8085/test/runnable/overload.d#L279
 
 - C++ chooses the function template
 
 - For me it's counterintuitive to call with conversion when an exact
   match can be instantiated. Even an ambiguous error seems more reasonable to
 me.
Right now I think that was little bad example. Ques. Why f3(1L) chooses non-template version? Short Ans. Because the given argument 1L is a literal. Long Ans. In D, literals works as like polysemous value. 1L is implicitly convertible to int by Value Range Propagation, so it matchs with MATCHconvert. If you give a runtime long value to f3: long n; f3(n); With first overload version, Phase 1: normal function is treated as having empty template parameter list, so matching is always exact ==> MATCHexact Phase 2: int <- n == MATCHnomatch (changed!!) With second overload version, Phase 1: T <- typeof(1L) = long ==> MATCHconvert Phase 2: T <- 1L == MATCHexact ==> MATCHexact So it will choose template version. How about? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 14 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528





 I find the C++ rule pretty plausible.
 
 In most cases a function template behaves just like a normal function when
 considering overload resolution. The template argument deduction is
 applied, if it succeeds, the function is added to the candidates set. Such
 a function is handled like any other function, except when two viable
 functions are equally good, the non-template one is selected. In case both
 are a specialisation of a function template, partial ordering rules are
 applied. The partial ordering rules are out of the scope of this article.
http://accu.org/index.php/journals/268#d0e340
C++ does not have template value parameters. The C++ behaviour is approximated closely when IFTI type parameter deduction is treated as exact match. (There is no reason to do anything else, a type is required, and a type is given.) However, it is not too clear that there must be one matching level for the template and one for the function. Kenji, why do you think this is required? Why does one matching level for everything not suffice? Eg, I think the following code should not compile and show an ambiguity error. void foo(double a)(int b){ } void foo(int a)(double b){ } void main(){ foo!1(1); } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 14 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528






It's not about the polysemous literals.
What's irritating me is that a function call with conversion
is preferred over a function template instantiation with
exact arguments.

int f3(long) { return 1; }
int f3(T)(T) { return 2; }

int v = 2;
f3(v);

MATCHexact / MATCHconvert vs.
MATCHconvert / MATCHexact

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 14 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528






 
 It's not about the polysemous literals.
 What's irritating me is that a function call with conversion
 is preferred over a function template instantiation with
 exact arguments.
 
 int f3(long) { return 1; }
 int f3(T)(T) { return 2; }
 
 int v = 2;
 f3(v);
 
 MATCHexact / MATCHconvert vs.
 MATCHconvert / MATCHexact
IMO the second should be MATCHexact / MATCHexact. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 14 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




---



 
 It's not about the polysemous literals.
 What's irritating me is that a function call with conversion
 is preferred over a function template instantiation with
 exact arguments.
 
 int f3(long) { return 1; }
 int f3(T)(T) { return 2; }
 
 int v = 2;
 f3(v);
 
 MATCHexact / MATCHconvert vs.
 MATCHconvert / MATCHexact
IMO the second should be MATCHexact / MATCHexact.
No. type parameter deduction is less specialized than matching to explicitly specialized type parameter. void foo(T)(T) {} // generic version void foo(T:int)(T) {} // specialized to int foo(1); // calls T:int version That is why f3(v) makes MATCHconvert / MATCHexact with template version. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 15 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528





 ...
 Parameter deduction is less specialized than matching to explicitly
 specialized type parameter.
 ...
It's not less specialized than a normal function call without type parameters. A type parameter should match a type argument exactly. Specialization mustn't be confused with the matching level -- it should be checked in a second step, as is done for functions. Why?: Specialization is a partial order, while the matching levels form a full order. There is no way to correctly implement specialization only by abusing matching levels. (At the very least, the logic for template specialization should not interfere with template vs. function overloading!) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 15 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




---


 ...
 Parameter deduction is less specialized than matching to explicitly
 specialized type parameter.
 ...
It's not less specialized than a normal function call without type parameters. A type parameter should match a type argument exactly. Specialization mustn't be confused with the matching level -- it should be checked in a second step, as is done for functions. Why?: Specialization is a partial order, while the matching levels form a full order. There is no way to correctly implement specialization only by abusing matching levels. (At the very least, the logic for template specialization should not interfere with template vs. function overloading!)
I talked the expected behavior by using the words used in dmd implementation. Yes, MATCH(exact|const|convert|nomatch) might not be the best word to talk language specification. But it is not a true problem. Essentially the thing I talking is: void foo(int) {} // 1 void foo(T:int)(T) {} // 2 void foo(T)(T) {} // 3 foo(1); Non template function (1) is specialized _as same as_ explicitly specialized template function (2). Then, normally deduced template function is less specialized than (1) and (2). My patch represents the specialization order for IFTI by the pair of MATCH value. And, (3) is represented by MATCHconvert / MATCHexact internally. Do not confuse internal representation and expected language specification/behavior. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 15 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




07:33:07 PDT ---
Great thread. Sorry I'm late to it! Let me make an appeal to simplicity - even
if we come up with a very meaningful and consistent set of overloading rules,
we lose if they are complicated. Simplicity is very important for figuring out
what function will be called in a context.

In that spirit I'd like to propose a basic strategy as follows:

1. Define a SIMPLE partial ordering relation <= between functions called "at
least as specialized" (and correspondingly a strict version < meaning "more
specialized").

2. Whenever two or more functions match a call, there is a "winner" only if it
is more specialized than all other candidates. (Not all candidates must be
partially ordered among themselves, but the winner must be more specialized
than all others.) Otherwise, there is ambiguity.

Now for the simple partial ordering relation: consider a call to a function
fun(args) with two overloads fun1 and fun2 that would accept the arguments,
i.e. fun1(args) and fun2(args) would both compile in isolation.

To decide whether fun1 and fun2 are partially ordered, we look at the sets of
accepted arguments. If fun2 accepts any argument fun1 would accept, we write
fun1 <= fun2 and we say "fun1 is at least as specialized as fun2" or "fun2 is
not more specialized than fun1".

Now, if fun1 <= fun2 and fun2 <= fun1 then the two are "as specialized" so a
decision cannot be made between the two. If only one of the relations applies,
then one of them is strictly more specialized and it is preferred in an
overloaded call. If neither relation applies, the functions are unordered so
again a decision cannot be made.

On the examples given by Kenji:

    int f1(int a, double=10) { return 1; }
    int f1(int a, string="") { return 2; }

These functions are not ordered because e.g. f1(2, 3.4) would not be accepted
by the second overload and f1(2, "hello") would not be accepted. So the call
f1(5) is ambiguous.

    int f2(T:int)(T b, double=10) { return 1; }
    int f2(T:int)(T b, string="") { return 2; }

Same here, these overloads are not ordered.

    // vs deduced parameter
    int f3(int a) { return 1; }
    int f3(T)(T b) { return 2; }

Here the second overload accepts f3("hello") so the first overload is more
specialized. It will be preferred even in calls with an implicit conversion,
e.g. f3(cast(short) 42). THIS IS A DEPARTURE FROM C++'S RULES.

    // vs specialized parameter
    int f4(int a) { return 1; }
    int f4(T:int)(T b) { return 2; }

These two functions are in the same equivalence classes because they accept the
same argument sets: f4_1 <= f4_2 and f4_2 <= f4_1. So any call that would match
these two would be ambiguous. 

    // vs deduced parameter + template constraint (1)
    int f5(int a) { return 1; }
    int f5(T)(T b) if (is(T == int)) { return 2; }

The constraint is evaluated first and then "disappears" leaving two functions.
Of these, the non-template is more specialized.

    // vs deduced parameter + template constraint (2)
    int f6(int a) { return 1; }
    int f6(T)(T b) if (is(T : int)) { return 2; }

Same here. Given that the constraints are arbitrary Boolean expressions, we
can't make good estimates on what sets of arguments they'll match.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 07 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




---

[snip]

That's the rule described in TDPL. I can completely agree with you.
I believe that my patch implements it enough.

----

I'd like to add one note for your better understand.

     // vs specialized parameter
     int f4(int a) { return 1; }
     int f4(T:int)(T b) { return 2; }
 
 These two functions are in the same equivalence classes because they accept
 the same argument sets: f4_1 <= f4_2 and f4_2 <= f4_1. So any call that would
 match these two would be ambiguous. 
That's true if and only if one int argument is given. In D, the template specialized parameter (T:int) means "T should exactly matches to int". int fx(T:int)(T b) { return 2; } void main() { fx(1L); } test.d(2): Error: template test.fx does not match any function template declaration. Candidates are: test.d(1): test.fx(T : int)(T b) test.d(2): Error: template test.fx(T : int)(T b) cannot deduce template function from argument types !()(long) So, f4 would match to non-template version if a non-int argument is given. assert(f4(1L) == 1); // not ambiguous -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 07 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




19:13:35 PDT ---
 Kenji: My bad, I forgot T:int means exact match, thought it's match with
conversion. (BTW that's a mistake: The syntax in classes suggests that class
T:U means subtyping. But it's too late to fix that now.)

So, you're right. Thanks for the clarification! Have you linked a pull request
yet?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 07 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull



---

  Kenji: My bad, I forgot T:int means exact match, thought it's match with
 conversion. (BTW that's a mistake: The syntax in classes suggests that class
 T:U means subtyping. But it's too late to fix that now.)
 
 So, you're right. Thanks for the clarification! Have you linked a pull request
 yet?
Oh, I forgot to add 'pull' tag. Will do. https://github.com/D-Programming-Language/dmd/pull/1409 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 07 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528




Commits pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/edd0f6fbeeff70eccd7d2e15429b20418360eca5
fix Issue 1528 - [tdpl] overloading template and non-template functions

- Improve `resolveFuncCall` for integrated function call resolution.
  All of error reporting is done in here.

- Remove `overloadResolve` and `deduceFuncitonTemplate`
  The works was in `overloadResolve` are moved to `resolveFuncCall`,
  and things was in `deduceFuncitonTemplate` are divided to
  `templateResolve` and `resolveFuncCall`.

- Change the name from `overloadResolveX` to `functionResolve`
  It is paired with `templateResolve`.

- Decide 'most specialized' function based on the two `MATCH` values derived
from `tiargs` and `fargs`.
  With non template functions, `last matching level for tiargs` is treated as
`MATCHexact`.

----
The bug that is fixed at the same time:
fix Issue 9596 - Ambiguous match is incorrectly hidden by additional lesser
match

  The change in test/runnable/template9.d is related.

https://github.com/D-Programming-Language/dmd/commit/fba440cc7dc1210b0450f8b01d18661ebbd0da55


Issue 1528 - [tdpl] overloading template and non-template functions

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 28 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


bearophile_hugs eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs eml.cc




 Commits pushed to master at 
This is a significant improvement. I am testing this feature a little. This is code reduced from your Comment 10: int f1(int a, double=10) { return 1; } int f1(int a, string="") { return 2; } int f2(T:int)(T b, double=10) { return 1; } int f2(T:int)(T b, string="") { return 2; } void main() { f1(1); f2(1L); } It gives the errors: test.d(6): Error: called with argument types: (int) matches both: test.d(1): test.f1(int a, double _param_1 = 10.0000) and: test.d(2): test.f1(int a, string _param_1 = "") test.d(7): Error: template test.f2 does not match any function template declaration. Candidates are: test.d(3): test.f2(T : int)(T b, double = 10) test.d(4): test.f2(T : int)(T b, string = "") test.d(7): Error: template test.f2(T : int)(T b, double = 10) cannot deduce template function from argument types !()(long) For the error at line 6 it nicely indents the lines test.d(1) and test.d(2). While for the error at line 7 it doesn't indent the lines test.d(3) and test.d(4). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 28 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Jonathan M Davis <jmdavisProg gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |mitch.hayenga gmail.com



PDT ---
*** Issue 4749 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 20 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 23 2013