Thread overview
[Issue 337] New: IFTI and overloading are incompatible
Sep 10, 2006
d-bugmail
[Issue 337] Function Templates cannot be overloaded
Sep 26, 2006
d-bugmail
defaulting leading template parameters?
Oct 25, 2006
Sean Kelly
Nov 01, 2006
Bruno Medeiros
Nov 01, 2006
Sean Kelly
Oct 25, 2006
d-bugmail
Dec 17, 2006
d-bugmail
Jun 11, 2008
d-bugmail
Jun 13, 2008
d-bugmail
[Issue 337] Function templates cannot be overloaded
Jan 01, 2012
Stewart Gordon
September 10, 2006
http://d.puremagic.com/issues/show_bug.cgi?id=337

           Summary: IFTI and overloading are incompatible
           Product: D
           Version: 0.166
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: major
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla@digitalmars.com
        ReportedBy: mclysenk@mtu.edu


Two overloaded template functions with the same template signature will cause a name conflict.  Here is an example:

//----

import std.stdio;

void testfunc(T)(T a)
{
    writefln("a = %s", a);
}

void testfunc(T)(int x, T a)
{
    writefln("x = %d, a = %s", x, a);
}

void main()
{
    testfunc("test1");
    testfunc(10, "test2");
}

//----

In this situation there is a name conflict between the two overloads of testfunc since their templates have the exact same signature.  One solution is to wrap them both inside a single template as follows:

//----
template testfunc(T)
{
    void testfunc(T a) { ... }
    void testfunc(int x, T a) { ... }
}

//----

However, testfunc is no longer considered a function template after such an operation, and IFTI is no longer applied.  This approach also prevents other modules from performing an overload on testfunc, such as declaring something like:

//----
void testfunc(T)(int x, int y, T a)
{
    writefln("x = %d, y = %d, a = %s", x, y, a);
}
//----

This will result in a name conflict with the previous declarations.  One solution is to add all of the types in testfunc to the template specification like this:

//----
void testfunc(Tx : int, Ta)(Tx x, Ta a)
{
    writefln("x = %d, a = %s", x, a);
}
//----

Unfortunately this gives the error:

modname.d(xx): template modname.testfunc(Tx : int,Ta) specialization not
allowed for deduced parameter Tx


The situation becomes even worse if the type of Tx is deduced from Ta, such as a delegate or another template instance:

void foreach_wrapper(T)(T[] a, void delegate(inout T) dg);
void foreach_wrapper(T)(T[] a, void delegate(int, inout T) dg);


-- 

September 26, 2006
http://d.puremagic.com/issues/show_bug.cgi?id=337


brunodomedeiros+bugz@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|IFTI and overloading are    |Function Templates cannot be
                   |incompatible                |overloaded




------- Comment #1 from brunodomedeiros+bugz@gmail.com  2006-09-26 05:47 -------
Saying this is IFTI related isn't exactly accurate. Since the problem occurs at template definition, no instantiation is need (implicit or explicit).

I'm not sure this is a bug (an enhancement perhaps). The spec is not explicit,
but only functions can be overloaded, or templates with different
specializations. Templated functions are templates foremost (not functions), so
they can only be overloaded if the specialization is different, which is not
the case.
However I think the following workarounds work (without loss of functionality)
:

* For overload based on number of parameters only:
--------
import std.stdio;

void testfunc(T)(T a) {
    writefln("a = %s", a);
}

void testfunc(DUMMY = void, T)(int x, T a) {
    writefln("x = %d, a = %s", x, a);
}

void main() {
    testfunc("test1");
    testfunc(10, "test2");
}
----

* For any kind of overload (just make dummy specializations):
--------
void foreach_wrapper(T)(T[] a, void delegate(inout T) dg) { }
void foreach_wrapper(DUMMY : int=int, T)(T[] a, void delegate(int, T) dg) {
    pragma(msg, "Second specialization");
}
void foreach_wrapper(DUMMY : char=char, T)(T[] a, void delegate(char, T) dg) {
    pragma(msg, "Third specialization");
}

void main()
{
    void delegate(int, inout byte) dg1;
    foreach_wrapper(new byte[3], dg1);

    void delegate(char, inout byte) dg2;
    foreach_wrapper(new byte[3], dg2);
}
----


-- 

October 25, 2006
http://d.puremagic.com/issues/show_bug.cgi?id=337


bugzilla@digitalmars.com changed:

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




------- Comment #2 from bugzilla@digitalmars.com  2006-10-25 17:46 -------
I agree with Bruno. While it isn't pretty, the workarounds he presented get us past the problem.


-- 

October 25, 2006
d-bugmail@puremagic.com wrote:
> 
> void testfunc(DUMMY = void, T)(int x, T a) {
>     writefln("x = %d, a = %s", x, a);
> }

I had no idea this was legal--it isn't in C++.  I guess the rationale is that if the compiler can figure out the remaining parameters by inspecting function arguments then this is not an error?


Sean
November 01, 2006
Sean Kelly wrote:
> d-bugmail@puremagic.com wrote:
>>
>> void testfunc(DUMMY = void, T)(int x, T a) {
>>     writefln("x = %d, a = %s", x, a);
>> }
> 
> I had no idea this was legal--it isn't in C++.  I guess the rationale is that if the compiler can figure out the remaining parameters by inspecting function arguments then this is not an error?
> 
> 
> Sean

Well, I've never actually learned C++ templates[*], so I my thinking isn't bound to what C++ can or cannot do :P . Anyway, I'm not sure I understand your question. At the time I just checked the docs to see what could be done with IFTI, and it was stated that:
"Template arguments not implicitly deduced can have default values:
  void Foo(T, U=T*)(T t) { U p; ... }
"
So in both explicit and implicit instantiation you can also have parameters that are deduced from other parameters. (Not the case in C++ then?) The DUMMY case above is just a case where such deduction is constant and not actually dependent on any other parameters.

[*] Well, I did a learn some of C++ templates, but only the basics, and only after learning D's and also usually under the perspective of D comparison.

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
November 01, 2006
Bruno Medeiros wrote:
> Sean Kelly wrote:
>> d-bugmail@puremagic.com wrote:
>>>
>>> void testfunc(DUMMY = void, T)(int x, T a) {
>>>     writefln("x = %d, a = %s", x, a);
>>> }
>>
>> I had no idea this was legal--it isn't in C++.  I guess the rationale is that if the compiler can figure out the remaining parameters by inspecting function arguments then this is not an error?
> 
> Well, I've never actually learned C++ templates[*], so I my thinking isn't bound to what C++ can or cannot do :P . Anyway, I'm not sure I understand your question. At the time I just checked the docs to see what could be done with IFTI, and it was stated that:
> "Template arguments not implicitly deduced can have default values:
>   void Foo(T, U=T*)(T t) { U p; ... }
> "
> So in both explicit and implicit instantiation you can also have parameters that are deduced from other parameters. (Not the case in C++ then?) The DUMMY case above is just a case where such deduction is constant and not actually dependent on any other parameters.

In C++, template parameter defaults work just like function parameter defaults--they can only be used for the final N parameters.  Also, defaults can only be used for classes in C++, not functions.  But I really like the way D works here instead.


Sean
December 17, 2006
http://d.puremagic.com/issues/show_bug.cgi?id=337





------- Comment #3 from wbaxter@gmail.com  2006-12-17 02:42 -------
(In reply to comment #2)
> I agree with Bruno. While it isn't pretty, the workarounds he presented get us past the problem.
> 

So why can't this sort of workaround be applied automatically by the compiler. The need to stick a dummy parameter in to work around the inability to overload templates is about as FAR from obvious as it gets.


-- 

June 11, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=337


larsivar@igesund.net changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|WONTFIX                     |




------- Comment #4 from larsivar@igesund.net  2008-06-11 02:20 -------
IFTI is next to useless without properly working overload of ifti functions.


-- 

June 13, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=337





------- Comment #5 from bugzilla@digitalmars.com  2008-06-13 04:10 -------
//----
void testfunc(Tx : int, Ta)(Tx x, Ta a)
{
    writefln("x = %d, a = %s", x, a);
}
//----

works with current versions of both D1.0 and D2.0.


-- 

January 01, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=337


Stewart Gordon <smjg@iname.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |spec
                 CC|                            |smjg@iname.com
            Summary|Function Templates cannot   |Function templates cannot
                   |be overloaded               |be overloaded
           Severity|major                       |enhancement


--- Comment #6 from Stewart Gordon <smjg@iname.com> 2012-01-01 15:53:53 PST ---
I agree with the analysis - two templates can't have the same signature.  So it would be a matter of changing the language to allow it if they can be instantiated in a way that disambiguates them.

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