www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Class template argument deduction from constructor call

reply sergk <kovrov+puremagic gmail.com> writes:
class Foo(T) {
    this(T t) {
        bar = t;
    }
    T bar;
}

void main() {
    auto a = new Foo(123); // doesn't work
    auto b = new Foo!(int)(123); // work, but redundant
}

Is there any technical limitations preventing this, or its just a compiler bug?


-- 
serg.
Oct 27 2010
parent reply div0 <div0 sourceforge.net> writes:
On 27/10/2010 20:36, sergk wrote:
 class Foo(T) {
      this(T t) {
          bar = t;
      }
      T bar;
 }

 void main() {
      auto a = new Foo(123); // doesn't work
      auto b = new Foo!(int)(123); // work, but redundant
 }

 Is there any technical limitations preventing this, or its just a compiler bug?
It's not a bug. I guess it could be a short cut, but it can only ever work when the class has exactly one constructor, which seems a bit of a pointless short cut and adds an unneccassiry corner case to the language spec. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Oct 27 2010
parent reply =?UTF-8?B?IkrDqXLDtG1lIE0uIEJlcmdlciI=?= <jeberger free.fr> writes:
div0 wrote:
 On 27/10/2010 20:36, sergk wrote:
 class Foo(T) {
      this(T t) {
          bar =3D t;
      }
      T bar;
 }

 void main() {
      auto a =3D new Foo(123); // doesn't work
      auto b =3D new Foo!(int)(123); // work, but redundant
 }

 Is there any technical limitations preventing this, or its just a
 compiler bug?
=20 It's not a bug. =20 I guess it could be a short cut, but it can only ever work when the class has exactly one constructor, which seems a bit of a pointless short cut and adds an unneccassiry corner case to the language spec. =20
Why would it only be able to work when there is exactly one constructor? Doesn't function overloading work with templates? This works here: void foo(T) (T x) { } void foo(T, U) (T x, U y) { } void main() { foo (3); foo (3, "azerty"); } Jerome --=20 mailto:jeberger free.fr http://jeberger.free.fr Jabber: jeberger jabber.fr
Oct 27 2010
parent reply div0 <div0 sourceforge.net> writes:
On 27/10/2010 21:02, "Jérôme M. Berger" wrote:
 div0 wrote:
 On 27/10/2010 20:36, sergk wrote:
 class Foo(T) {
       this(T t) {
           bar = t;
       }
       T bar;
 }

 void main() {
       auto a = new Foo(123); // doesn't work
       auto b = new Foo!(int)(123); // work, but redundant
 }

 Is there any technical limitations preventing this, or its just a
 compiler bug?
It's not a bug. I guess it could be a short cut, but it can only ever work when the class has exactly one constructor, which seems a bit of a pointless short cut and adds an unneccassiry corner case to the language spec.
Why would it only be able to work when there is exactly one constructor? Doesn't function overloading work with templates? This works here: void foo(T) (T x) { } void foo(T, U) (T x, U y) { } void main() { foo (3); foo (3, "azerty"); } Jerome
class Foo(T) { this(T t) { bar = t; } this(string x) { } this(int x) { } T bar; } auto f0 = new Foo("wtf?"); auto f1 = new Foo(42); What's T in any of the above? There's no obvious answer for the first 2 and anything anybody says will be a source of endless arguments and bike shedding. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Oct 27 2010
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, October 27, 2010 13:26:21 div0 wrote:
 On 27/10/2010 21:02, "J=C3=A9r=C3=B4me M. Berger" wrote:
 div0 wrote:
 On 27/10/2010 20:36, sergk wrote:
 class Foo(T) {
=20
       this(T t) {
      =20
           bar =3D t;
      =20
       }
       T bar;
=20
 }
=20
 void main() {
=20
       auto a =3D new Foo(123); // doesn't work
       auto b =3D new Foo!(int)(123); // work, but redundant
=20
 }
=20
 Is there any technical limitations preventing this, or its just a
 compiler bug?
=20 It's not a bug. =20 I guess it could be a short cut, but it can only ever work when the class has exactly one constructor, which seems a bit of a pointless short cut and adds an unneccassiry corner case to the language spec. =20
Why would it only be able to work when there is exactly one =20 constructor? Doesn't function overloading work with templates? =20 This works here: void foo(T) (T x) { } =20 void foo(T, U) (T x, U y) { } =20 void main() { =20 foo (3); foo (3, "azerty"); =20 } =20 Jerome
=20 class Foo(T) { this(T t) { bar =3D t; } =20 this(string x) { } =20 this(int x) { } =20 T bar; } =20 auto f0 =3D new Foo("wtf?"); auto f1 =3D new Foo(42); =20 What's T in any of the above? =20 There's no obvious answer for the first 2 and anything anybody says will be a source of endless arguments and bike shedding.
The obvious answer would be that this shouldn't compile because it's ambigu= ous.=20 If you force the constructors which conflict with the templated constructor= to be=20 template specializations, then the problem goes away. However, IIRC,=20 unfortunately, at the moment, you can't have a function which has a templat= ed=20 and non-templated version regardless of the number of parameters, though I= =20 believe that there is a bug report on it. =2D Jonathan M Davis
Oct 27 2010
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 27 Oct 2010 16:26:21 -0400, div0 <div0 sourceforge.net> wrote:

 On 27/10/2010 21:02, "Jérôme M. Berger" wrote:
 div0 wrote:
 On 27/10/2010 20:36, sergk wrote:
 class Foo(T) {
       this(T t) {
           bar = t;
       }
       T bar;
 }

 void main() {
       auto a = new Foo(123); // doesn't work
       auto b = new Foo!(int)(123); // work, but redundant
 }

 Is there any technical limitations preventing this, or its just a
 compiler bug?
It's not a bug. I guess it could be a short cut, but it can only ever work when the class has exactly one constructor, which seems a bit of a pointless short cut and adds an unneccassiry corner case to the language spec.
Why would it only be able to work when there is exactly one constructor? Doesn't function overloading work with templates? This works here: void foo(T) (T x) { } void foo(T, U) (T x, U y) { } void main() { foo (3); foo (3, "azerty"); } Jerome
class Foo(T) { this(T t) { bar = t; } this(string x) { } this(int x) { } T bar; } auto f0 = new Foo("wtf?"); auto f1 = new Foo(42); What's T in any of the above?
translates to: auto f0 = new Foo!(string)("wtf?"); auto f0 = new Foo!(int)(42); Both of which error, since T can be neither int nor string, or Foo would contain conflicting constructors. Your question is akin to asking why IFTI doesn't work on something like this: T foo(T)(int x); What Jerome was referring to is something like this: class Foo(T) { this(T t) {} this(T t, string x); } which should be unambiguous and completely doable. The thing is, when a templated class is to be instantiated without giving a complete set of template arguments, then it should use IFTI. The decision to try IFTI is not ambiguous, but depending on how you implement the constructors, the overloading can be ambiguous. To answer the OP's question, I don't think there's anything technical restricting the compiler from doing this. I believe it's been proposed several times. If you want to, you can work around the issue by making a wrapper constructor function: Foo!T makeFoo(T)(T t) { return new Foo!T(t); } -Steve
Oct 27 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 27 Oct 2010 22:10:24 -0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:


 To answer the OP's question, I don't think there's anything technical  
 restricting the compiler from doing this.  I believe it's been proposed  
 several times.  If you want to, you can work around the issue by making  
 a wrapper constructor function:

 Foo!T makeFoo(T)(T t)
 {
    return new Foo!T(t);
 }
I should add, it would be ambiguous to do something like this: class Foo(T, U) { this(T t, U u) {} this(U u, T t) {} } This kind of situation currently doesn't exist in IFTI, since only templates that have exactly one member and it is a function can participate in IFTI. But if the classes are made to work in normal cases, then I think IFTI can be extended to support this kind of thing -Steve
Oct 27 2010
prev sibling parent =?UTF-8?B?IkrDqXLDtG1lIE0uIEJlcmdlciI=?= <jeberger free.fr> writes:
Steven Schveighoffer wrote:
 On Wed, 27 Oct 2010 16:26:21 -0400, div0 <div0 sourceforge.net> wrote:
=20
 class Foo(T) {
         this(T t) {
             bar =3D t;
         }

     this(string x) {
     }

     this(int x) {
     }

         T bar;
 }

 auto    f0 =3D new Foo("wtf?");
 auto    f1 =3D new Foo(42);

 What's T in any of the above?
=20 translates to: auto f0 =3D new Foo!(string)("wtf?"); auto f0 =3D new Foo!(int)(42); =20 Both of which error, since T can be neither int nor string, or Foo woul=
d
 contain conflicting constructors.
=20
 Your question is akin to asking why IFTI doesn't work on something like=
 this:
=20
 T foo(T)(int x);
=20
 What Jerome was referring to is something like this:
=20
 class Foo(T)
 {
   this(T t) {}
   this(T t, string x);
 }
=20
 which should be unambiguous and completely doable.
=20
 The thing is, when a templated class is to be instantiated without
 giving a complete set of template arguments, then it should use IFTI.=20
 The decision to try IFTI is not ambiguous, but depending on how you
 implement the constructors, the overloading can be ambiguous.
=20
Exactly, it should be possible to have consistent behaviour for template class constructors and template functions: they should both work and fail in similar circumstances. Jerome --=20 mailto:jeberger free.fr http://jeberger.free.fr Jabber: jeberger jabber.fr
Oct 28 2010
prev sibling parent Juanjo Alvarez <fake fakeemail.com> writes:
On Wed, 27 Oct 2010 21:26:21 +0100, div0 <div0 sourceforge.net> wrote:
         this(T t) {
 	this(string x) {
 	this(int x) {
 auto	f0 = new Foo("wtf?");
 auto	f1 = new Foo(42);
Best match?
Oct 29 2010