www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template method and overloading

reply gerleim <elf_qt _deletethisifyouarenotaspammer_yahoo.com> writes:
Why
"template test.A.Foo(T) conflicts with test.A.Foo(T) at ..."
?

public class A
{
	public void Foo(T)(T p1)
	{
	}

	public void Foo(T)(T p1, bool b)
	{
	}
}

The two methods has different signatures.
I'm not really familiar with c++ templates, but c#/.net can handle this.

What's the reason behind this, and will the behaviour change?

Thanks,
 gerleim
May 29 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
gerleim wrote:
 Why
 "template test.A.Foo(T) conflicts with test.A.Foo(T) at ..."
 ?
 
 public class A
 {
 	public void Foo(T)(T p1)
 	{
 	}
 
 	public void Foo(T)(T p1, bool b)
 	{
 	}
 }
 
 The two methods has different signatures.
 I'm not really familiar with c++ templates, but c#/.net can handle this.
 
 What's the reason behind this, and will the behaviour change?
 
 Thanks,
  gerleim

Yeh that's not allowed. I presume the reason was it was easier to implement this way. The workaround is to give them different *template* parameter lists. Something like: public void Foo(T)(T p1) { } public void Foo(T,dummy=float)(T p1, bool b) { } It's silly that you have to do that, but since that workaround is available, I don't think Walter considers fixing it a very high priority. --bb
May 29 2007
next sibling parent reply gerleim <elf_qt _deletethisifyouarenotaspammer_yahoo.com> writes:
Oh, I see, thanks. Didn't know that template parameter lists have to differ.
(Is that documented?)

I tried to workaround with a tuple template parameter.

gerleim

 Yeh that's not allowed.  I presume the reason was it was easier to 
 implement this way.
 The workaround is to give them different *template* parameter lists. 
 Something like:
   	public void Foo(T)(T p1)
   	{
   	}
 
   	public void Foo(T,dummy=float)(T p1, bool b)
   	{
   	}
 
 It's silly that you have to do that, but since that workaround is 
 available, I don't think Walter considers fixing it a very high priority.
 
 --bb

May 29 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"gerleim" <elf_qt _deletethisifyouarenotaspammer_yahoo.com> wrote in message 
news:f3hvvt$2q18$1 digitalmars.com...
 Oh, I see, thanks. Didn't know that template parameter lists have to 
 differ.
 (Is that documented?)

It's because templated functions are really just syntactic sugar. So: void foo(T)(int x){} void foo(T)(int x, float y){} Is really seen by the compiler as: template foo(T) { void foo(int x){} } template foo(T) { void foo(int x, float y){} } Now it looks obvious that there should be an error, because it's the templates that are at top-level, not the functions.
May 29 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:f3i3uc$2vkn$1 digitalmars.com...
 "gerleim" <elf_qt _deletethisifyouarenotaspammer_yahoo.com> wrote in 
 message news:f3hvvt$2q18$1 digitalmars.com...
 Oh, I see, thanks. Didn't know that template parameter lists have to 
 differ.
 (Is that documented?)

It's because templated functions are really just syntactic sugar. So: void foo(T)(int x){} void foo(T)(int x, float y){} Is really seen by the compiler as: template foo(T) { void foo(int x){} } template foo(T) { void foo(int x, float y){} } Now it looks obvious that there should be an error, because it's the templates that are at top-level, not the functions.

But after posting that, I now don't know how the compiler thinks this is any easier to deal with: template foo(T) { void foo(int x){} } template foo(T, dummy = void) { void foo(int x, float y){} } How does it find the foo(int x, float y)? Maybe it's buried in weird template rules I don't entirely understand..
May 29 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Jarrett Billingsley wrote:
 "Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
 news:f3i3uc$2vkn$1 digitalmars.com...
 "gerleim" <elf_qt _deletethisifyouarenotaspammer_yahoo.com> wrote in 
 message news:f3hvvt$2q18$1 digitalmars.com...
 Oh, I see, thanks. Didn't know that template parameter lists have to 
 differ.
 (Is that documented?)

void foo(T)(int x){} void foo(T)(int x, float y){} Is really seen by the compiler as: template foo(T) { void foo(int x){} } template foo(T) { void foo(int x, float y){} } Now it looks obvious that there should be an error, because it's the templates that are at top-level, not the functions.

But after posting that, I now don't know how the compiler thinks this is any easier to deal with: template foo(T) { void foo(int x){} } template foo(T, dummy = void) { void foo(int x, float y){} } How does it find the foo(int x, float y)? Maybe it's buried in weird template rules I don't entirely understand..

I think that's the SFINAE thing ("Somethinerother Failure Is Not An Error"). It tries one template, and that fails to work, so it just goes on to try the next until it finds one that works. Or maybe it finds all the ones that work then picks the "best match" of the lot. (if you have a foo(int T) and a foo(float T) for instance). Either way in the above example only one template instantiation works so it's not hard to decide. --bb
May 29 2007
parent Downs <default_357-line yahoo.de> writes:
Bill Baxter wrote:
 I think that's the SFINAE thing ("Somethinerother Failure Is Not An Error"

May 30 2007
prev sibling parent reply Ary Manzana <ary esperanto.org.ar> writes:
Bill Baxter escribió:
 Something like:
      public void Foo(T)(T p1)
      {
      }
 
      public void Foo(T,dummy=float)(T p1, bool b)
      {
      }
 
 It's silly that you have to do that, but since that workaround is 
 available, I don't think Walter considers fixing it a very high priority.

! This is so wrong. The language is trying to be elegant with "foreach", "delegate" and some other stuff, while there are holes in many other places, like this one. I'm not saying that it's bad the problem exists. I think it's bad fixing this kind of things has low priority, while adding new features to the language has high priority. I know fixing is boring, and new stuff is fun. But... Workaround Oriented Programming is not fun. :-(
May 30 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Ary Manzana wrote:
 Bill Baxter escribió:
 Something like:
      public void Foo(T)(T p1)
      {
      }

      public void Foo(T,dummy=float)(T p1, bool b)
      {
      }

 It's silly that you have to do that, but since that workaround is
 available, I don't think Walter considers fixing it a very high priority.

! This is so wrong. The language is trying to be elegant with "foreach", "delegate" and some other stuff, while there are holes in many other places, like this one. I'm not saying that it's bad the problem exists. I think it's bad fixing this kind of things has low priority, while adding new features to the language has high priority. I know fixing is boring, and new stuff is fun. But... Workaround Oriented Programming is not fun. :-(

I'm pretty sure this hasn't been fixed not because it's boring, but because it's hard. As Jarret said, the original code expands to two templates with exactly the same name and set of arguments. I mean, would you call it a bug that you can't have two methods with the same name and same arguments, but differ by their contents? This isn't so much a bug with D, but just a limitation. I vaguely remember someone (possibly Walter) saying at some point that fixing this would require changing the compiler to distinguish between templates and templated functions; which would require duplicating a lot of code, and making the front end a lot messier. When there's a simple (if ugly) workaround available, I don't see how this is more important than getting good const semantics. This you can work around. Working around a lack of good const is much harder :) -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 29 2007
parent reply Ary Manzana <ary esperanto.org.ar> writes:
I thought maybe the compiler could merge all the templates with the same 
name and template parameters... I think this is ok as long as you don't 
use mixins, because you'll end up mixing more stuff than what you really 
want...

Unless... the merge is documented somewhere, and so there will be no 
confusion at all. Most of the time you won't have two templated 
functions and then would want to mix them, or have a templated function 
and a raw template with the same name.

Is this possible?

Daniel Keep escribió:
 
 Ary Manzana wrote:
 Bill Baxter escribió:
 Something like:
      public void Foo(T)(T p1)
      {
      }

      public void Foo(T,dummy=float)(T p1, bool b)
      {
      }

 It's silly that you have to do that, but since that workaround is
 available, I don't think Walter considers fixing it a very high priority.

This is so wrong. The language is trying to be elegant with "foreach", "delegate" and some other stuff, while there are holes in many other places, like this one. I'm not saying that it's bad the problem exists. I think it's bad fixing this kind of things has low priority, while adding new features to the language has high priority. I know fixing is boring, and new stuff is fun. But... Workaround Oriented Programming is not fun. :-(

I'm pretty sure this hasn't been fixed not because it's boring, but because it's hard. As Jarret said, the original code expands to two templates with exactly the same name and set of arguments. I mean, would you call it a bug that you can't have two methods with the same name and same arguments, but differ by their contents? This isn't so much a bug with D, but just a limitation. I vaguely remember someone (possibly Walter) saying at some point that fixing this would require changing the compiler to distinguish between templates and templated functions; which would require duplicating a lot of code, and making the front end a lot messier. When there's a simple (if ugly) workaround available, I don't see how this is more important than getting good const semantics. This you can work around. Working around a lack of good const is much harder :) -- Daniel

May 30 2007
parent Ary Manzana <ary esperanto.org.ar> writes:
I've just tried it, it works.

---
module main;

import std.stdio;

template foo(T) {
	void foo(T x, int y) {
		writefln("In first with %s: %s", typeid(T), y);
	}
	void foo(T x, char[] y) {
		writefln("In second with %s: %s", typeid(T), y);
	}
}

void main() {
	int[] x;
	double[] y;
	
	foo!(int[]).foo(x, 1);
	foo!(double[]).foo(y, "hello");
}
---

Output:
In first with int[]: 1
In second with double[]: hello

The only problem is that you have to explicitly say which is T, because 
the "one member" rule dosen't apply anymore. Maybe the rule could be 
changed for functions, to allow this kind of overloads.

Is there any problem with this I'm not being able to see?

Ary Manzana escribió:
 I thought maybe the compiler could merge all the templates with the same 
 name and template parameters... I think this is ok as long as you don't 
 use mixins, because you'll end up mixing more stuff than what you really 
 want...
 
 Unless... the merge is documented somewhere, and so there will be no 
 confusion at all. Most of the time you won't have two templated 
 functions and then would want to mix them, or have a templated function 
 and a raw template with the same name.
 
 Is this possible?
 
 Daniel Keep escribió:
 Ary Manzana wrote:
 Bill Baxter escribió:
 Something like:
      public void Foo(T)(T p1)
      {
      }

      public void Foo(T,dummy=float)(T p1, bool b)
      {
      }

 It's silly that you have to do that, but since that workaround is
 available, I don't think Walter considers fixing it a very high 
 priority.

This is so wrong. The language is trying to be elegant with "foreach", "delegate" and some other stuff, while there are holes in many other places, like this one. I'm not saying that it's bad the problem exists. I think it's bad fixing this kind of things has low priority, while adding new features to the language has high priority. I know fixing is boring, and new stuff is fun. But... Workaround Oriented Programming is not fun. :-(

I'm pretty sure this hasn't been fixed not because it's boring, but because it's hard. As Jarret said, the original code expands to two templates with exactly the same name and set of arguments. I mean, would you call it a bug that you can't have two methods with the same name and same arguments, but differ by their contents? This isn't so much a bug with D, but just a limitation. I vaguely remember someone (possibly Walter) saying at some point that fixing this would require changing the compiler to distinguish between templates and templated functions; which would require duplicating a lot of code, and making the front end a lot messier. When there's a simple (if ugly) workaround available, I don't see how this is more important than getting good const semantics. This you can work around. Working around a lack of good const is much harder :) -- Daniel


May 30 2007