www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Let this() figure out T implicitly?

reply kraybourne <stdin kraybourne.com> writes:
Hi!

This doesn't work:

	import std.stdio;
	class Foo(T)
	{
		T t;
		this(T val)
		{
			t = val;
		}
	}

	void main()
	{
		auto o = new Foo(5);
	}
	_____

	$ dmd foo
	foo.d(13): Error: class foo.Foo(T) is used as a type
	$ _

So I must

	auto o = new Foo!(int)(5);

Then it compiles. Is it possible to have this() figure out the type some 
way? (In this particular example it's perhaps not such a big deal. But 
imagine a lot more args.)

(Side note: What _does_ that error message mean? I don't get it.)

thanks
/krbrn
Feb 17 2012
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
kraybourne:

 Then it compiles. Is it possible to have this() figure out the type some 
 way?

Usually people write a small global function helper.
 (Side note: What _does_ that error message mean? I don't get it.)

I think the meaning is: when a class template is not yet instantiated, it's not a type yet. Bye, bearophile
Feb 17 2012
parent kraybourne <stdin kraybourne.com> writes:
On 2/17/12 1:32 PM, bearophile wrote:
 kraybourne:

 Then it compiles. Is it possible to have this() figure out the type some
 way?

Usually people write a small global function helper.

Hm, so, something like this: Foo!(T) newFoo(T)(T val) { return new Foo!(T)(val); } ... auto o = newFoo(5); Works! Ha! How silly. Thanks!
 (Side note: What _does_ that error message mean? I don't get it.)

I think the meaning is: when a class template is not yet instantiated, it's not a type yet. Bye, bearophile

Feb 17 2012
prev sibling next sibling parent reply Kevin Cox <kevincox.ca gmail.com> writes:
--00151740269ce686b504b9286726
Content-Type: text/plain; charset=UTF-8

The error message is saying that you are trying to use Foo as a type but
Foo is not a type, it is a template for a type.
On Feb 17, 2012 7:20 AM, "kraybourne" <stdin kraybourne.com> wrote:

 Hi!

 This doesn't work:

        import std.stdio;
        class Foo(T)
        {
                T t;
                this(T val)
                {
                        t = val;
                }
        }

        void main()
        {
                auto o = new Foo(5);
        }
        _____

        $ dmd foo
        foo.d(13): Error: class foo.Foo(T) is used as a type
        $ _

 So I must

        auto o = new Foo!(int)(5);

 Then it compiles. Is it possible to have this() figure out the type some
 way? (In this particular example it's perhaps not such a big deal. But
 imagine a lot more args.)

 (Side note: What _does_ that error message mean? I don't get it.)

 thanks
 /krbrn

--00151740269ce686b504b9286726 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <p>The error message is saying that you are trying to use Foo as a type but= Foo is not a type, it is a template for a type.</p> <div class=3D"gmail_quote">On Feb 17, 2012 7:20 AM, &quot;kraybourne&quot; = &lt;<a href=3D"mailto:stdin kraybourne.com">stdin kraybourne.com</a>&gt; wr= ote:<br type=3D"attribution"><blockquote class=3D"gmail_quote" style=3D"mar= gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> Hi!<br> <br> This doesn&#39;t work:<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0import std.stdio;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0class Foo(T)<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0{<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0T t;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0this(T val)<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0{<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0t =3D val;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0void main()<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0{<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0auto o =3D new Foo(= 5);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0_____<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0$ dmd foo<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0foo.d(13): Error: class foo.Foo(T) is used as a= type<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0$ _<br> <br> So I must<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0auto o =3D new Foo!(int)(5);<br> <br> Then it compiles. Is it possible to have this() figure out the type some wa= y? (In this particular example it&#39;s perhaps not such a big deal. But im= agine a lot more args.)<br> <br> (Side note: What _does_ that error message mean? I don&#39;t get it.)<br> <br> thanks<br> /krbrn<br> </blockquote></div> --00151740269ce686b504b9286726--
Feb 17 2012
parent reply kraybourne <stdin kraybourne.com> writes:
On 2/17/12 1:51 PM, Kevin Cox wrote:
 The error message is saying that you are trying to use Foo as a type but
 Foo is not a type, it is a template for a type.

Ah, so module.Foo is really not a class, but a template? I think I get it! Thanks! (Is then module.Foo(int).Foo the actual class type? I think I've seen errors like that pop up...)
 On Feb 17, 2012 7:20 AM, "kraybourne" <stdin kraybourne.com
 <mailto:stdin kraybourne.com>> wrote:

     Hi!

     This doesn't work:

             import std.stdio;
             class Foo(T)
             {
                     T t;
                     this(T val)
                     {
                             t = val;
                     }
             }

             void main()
             {
                     auto o = new Foo(5);
             }
             _____

             $ dmd foo
             foo.d(13): Error: class foo.Foo(T) is used as a type
             $ _

     So I must

             auto o = new Foo!(int)(5);

     Then it compiles. Is it possible to have this() figure out the type
     some way? (In this particular example it's perhaps not such a big
     deal. But imagine a lot more args.)

     (Side note: What _does_ that error message mean? I don't get it.)

     thanks
     /krbrn

Feb 17 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/17/2012 02:07 PM, Kevin Cox wrote:
 Yes.  At least as the compiler would say.  It's a little odd but I
 believe that is how the D Nam mangling works.  I personally just think
 of Foo!(Class) as the type.

class Foo(T){ ... } Is syntactic sugar for template Foo(T){ class Foo{ ... } } Therefore the type is Foo!(Class).Foo. I'd prefer the compiler to output Foo!(Class) in error messages and for .stringof though, vote here: http://d.puremagic.com/issues/show_bug.cgi?id=7064
Feb 17 2012
parent kraybourne <stdin kraybourne.com> writes:
On 2/17/12 2:38 PM, Timon Gehr wrote:
 On 02/17/2012 02:07 PM, Kevin Cox wrote:
 Yes. At least as the compiler would say. It's a little odd but I
 believe that is how the D Nam mangling works. I personally just think
 of Foo!(Class) as the type.

class Foo(T){ ... } Is syntactic sugar for template Foo(T){ class Foo{ ... } } Therefore the type is Foo!(Class).Foo.

Aaah, I see, clever, thx
 I'd prefer the compiler to output
 Foo!(Class) in error messages and for .stringof though, vote here:

 http://d.puremagic.com/issues/show_bug.cgi?id=7064

Feb 17 2012
prev sibling next sibling parent Kevin Cox <kevincox.ca gmail.com> writes:
--00151740269ccbbaca04b928a0bd
Content-Type: text/plain; charset=UTF-8

Yes.  At least as the compiler would say.  It's a little odd but I believe
that is how the D Nam mangling works.  I personally just think of
Foo!(Class) as the type.
On Feb 17, 2012 8:05 AM, "kraybourne" <stdin kraybourne.com> wrote:

 On 2/17/12 1:51 PM, Kevin Cox wrote:

 The error message is saying that you are trying to use Foo as a type but
 Foo is not a type, it is a template for a type.

Thanks! (Is then module.Foo(int).Foo the actual class type? I think I've seen errors like that pop up...) On Feb 17, 2012 7:20 AM, "kraybourne" <stdin kraybourne.com
 <mailto:stdin kraybourne.com>> wrote:

    Hi!

    This doesn't work:

            import std.stdio;
            class Foo(T)
            {
                    T t;
                    this(T val)
                    {
                            t = val;
                    }
            }

            void main()
            {
                    auto o = new Foo(5);
            }
            _____

            $ dmd foo
            foo.d(13): Error: class foo.Foo(T) is used as a type
            $ _

    So I must

            auto o = new Foo!(int)(5);

    Then it compiles. Is it possible to have this() figure out the type
    some way? (In this particular example it's perhaps not such a big
    deal. But imagine a lot more args.)

    (Side note: What _does_ that error message mean? I don't get it.)

    thanks
    /krbrn


--00151740269ccbbaca04b928a0bd Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <p>Yes.=C2=A0 At least as the compiler would say.=C2=A0 It&#39;s a little o= dd but I believe that is how the D Nam mangling works.=C2=A0 I personally j= ust think of Foo!(Class) as the type.</p> <div class=3D"gmail_quote">On Feb 17, 2012 8:05 AM, &quot;kraybourne&quot; = &lt;<a href=3D"mailto:stdin kraybourne.com">stdin kraybourne.com</a>&gt; wr= ote:<br type=3D"attribution"><blockquote class=3D"gmail_quote" style=3D"mar= gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> On 2/17/12 1:51 PM, Kevin Cox wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> The error message is saying that you are trying to use Foo as a type but<br=

<br> </blockquote> <br> Ah, so module.Foo is really not a class, but a template? I think I get it! = Thanks!<br> <br> (Is then module.Foo(int).Foo the actual class type? I think I&#39;ve seen e= rrors like that pop up...)<br> <br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> On Feb 17, 2012 7:20 AM, &quot;kraybourne&quot; &lt;<a href=3D"mailto:stdin= kraybourne.com" target=3D"_blank">stdin kraybourne.com</a><br> &lt;mailto:<a href=3D"mailto:stdin kraybourne.com" target=3D"_blank">stdin = kraybourne.com</a>&gt;&gt; wrote:<br> <br> =C2=A0 =C2=A0Hi!<br> <br> =C2=A0 =C2=A0This doesn&#39;t work:<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0import std.stdio;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0class Foo(T)<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0{<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0T t;<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0this(= T val)<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0{<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0t =3D val;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0void main()<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0{<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0auto = o =3D new Foo(5);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0_____<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0$ dmd foo<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0foo.d(13): Error: class foo.Foo(T= ) is used as a type<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0$ _<br> <br> =C2=A0 =C2=A0So I must<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0auto o =3D new Foo!(int)(5);<br> <br> =C2=A0 =C2=A0Then it compiles. Is it possible to have this() figure out th= e type<br> =C2=A0 =C2=A0some way? (In this particular example it&#39;s perhaps not su= ch a big<br> =C2=A0 =C2=A0deal. But imagine a lot more args.)<br> <br> =C2=A0 =C2=A0(Side note: What _does_ that error message mean? I don&#39;t = get it.)<br> <br> =C2=A0 =C2=A0thanks<br> =C2=A0 =C2=A0/krbrn<br> <br> </blockquote> <br> </blockquote></div> --00151740269ccbbaca04b928a0bd--
Feb 17 2012
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 17 Feb 2012 07:19:28 -0500, kraybourne <stdin kraybourne.com>  
wrote:

 Hi!

 This doesn't work:

 	import std.stdio;
 	class Foo(T)
 	{
 		T t;
 		this(T val)
 		{
 			t = val;
 		}
 	}

 	void main()
 	{
 		auto o = new Foo(5);
 	}
 	_____

 	$ dmd foo
 	foo.d(13): Error: class foo.Foo(T) is used as a type
 	$ _

 So I must

 	auto o = new Foo!(int)(5);

 Then it compiles. Is it possible to have this() figure out the type some  
 way? (In this particular example it's perhaps not such a big deal. But  
 imagine a lot more args.)

What you are asking for is IFTI (Implicit Function Template Instantiation) on constructors, and is perfectly possible, but not implemented: http://d.puremagic.com/issues/show_bug.cgi?id=6082 Vote up if you want to see it happen! -Steve
Feb 17 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/17/2012 09:08 AM, Steven Schveighoffer wrote:

 What you are asking for is IFTI (Implicit Function Template
 Instantiation) on constructors, and is perfectly possible, but not
 implemented:

 http://d.puremagic.com/issues/show_bug.cgi?id=6082

What was the resolution for the case when the constructor is a template? I think that's why IFTI doesn't work for structs and classes in C++. Although, I can't get the following to compile in D anyway (that old and annoying error message again! :p): Error: no property 'opCall' for type 'deneme.B' import std.conv; class B { string s; this(T)(T t) // <-- Is the struct a template // or the constructor a template? { s = to!string(t); } } void main() { auto b0 = B(42); } I wasn't around when the static opCall() was designed but it is probably the very first thing that bugged me about D. :) I want B(42) to be object construction, not opCall(), which is not even defined. Ali
Feb 17 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/18/2012 12:04 AM, Ali Çehreli wrote:
 On 02/17/2012 09:08 AM, Steven Schveighoffer wrote:

  > What you are asking for is IFTI (Implicit Function Template
  > Instantiation) on constructors, and is perfectly possible, but not
  > implemented:
  >
  > http://d.puremagic.com/issues/show_bug.cgi?id=6082

 What was the resolution for the case when the constructor is a template?
 I think that's why IFTI doesn't work for structs and classes in C++.
 Although, I can't get the following to compile in D anyway (that old and
 annoying error message again! :p):

    Error: no property 'opCall' for type 'deneme.B'

 import std.conv;

 class B
 {
      string s;

      this(T)(T t)   // <-- Is the struct a template
                     //     or the constructor a template?

The constructor it is, and B is a class, not a struct.
      {
          s = to!string(t);
      }
 }

 void main()
 {
      auto b0 = B(42);
 }

 I wasn't around when the static opCall() was designed but it is probably
 the very first thing that bugged me about D. :) I want B(42) to be
 object construction, not opCall(), which is not even defined.

 Ali

Why? What useful semantics would that have for classes?
Feb 17 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/17/2012 05:59 PM, Timon Gehr wrote:
 On 02/18/2012 12:04 AM, Ali Çehreli wrote:
 On 02/17/2012 09:08 AM, Steven Schveighoffer wrote:

 What you are asking for is IFTI (Implicit Function Template
 Instantiation) on constructors, and is perfectly possible, but not
 implemented:

 http://d.puremagic.com/issues/show_bug.cgi?id=6082

What was the resolution for the case when the constructor is a template? I think that's why IFTI doesn't work for structs and classes in C++. Although, I can't get the following to compile in D anyway (that old and annoying error message again! :p): Error: no property 'opCall' for type 'deneme.B' import std.conv; class B { string s; this(T)(T t) // <-- Is the struct a template // or the constructor a template?

The constructor it is, and B is a class, not a struct.

Ah! Thanks! So today the following works; and not B, but the constructor is a template: import std.conv; struct B { string s; this(T)(T t) // <-- constructor is a template { s = to!string(t); } } void main() { auto b0 = B(42); // construct with int assert(b0.s == "42"); auto b1 = B(1.5); // construct with double assert(b1.s == "1.5"); } With the proposed feature, the struct would be a template.
 {
 s = to!string(t);
 }
 }

 void main()
 {
 auto b0 = B(42);
 }

 I wasn't around when the static opCall() was designed but it is probably
 the very first thing that bugged me about D. :) I want B(42) to be
 object construction, not opCall(), which is not even defined.

 Ali

Why? What useful semantics would that have for classes?

I am not sure but the point is, if function templates provide IFTI, then because of being functions the constructors could provide IFTI as well, as it does for the struct B above. As an aside, I don't know why it is not the same with classes. I hope I am not again making an error in the following code. I have replaced 'struct' with 'class' and inserted two 'new' keywords: import std.conv; class B { string s; this(T)(T t) { s = to!string(t); } } void main() { auto b0 = new B(42); // line 61459 assert(b0.s == "42"); auto b1 = new B(1.5); // line 61462 assert(b1.s == "1.5"); } The compiler says: deneme.d(61459): Error: no constructor for B deneme.d(61462): Error: no constructor for B deneme.d(61462): Warning: statement is not reachable Ali
Feb 17 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 02/18/2012 03:22 AM, Ali Çehreli wrote:
 On 02/17/2012 05:59 PM, Timon Gehr wrote:
  > On 02/18/2012 12:04 AM, Ali Çehreli wrote:
  >> On 02/17/2012 09:08 AM, Steven Schveighoffer wrote:
  >>
  >> > What you are asking for is IFTI (Implicit Function Template
  >> > Instantiation) on constructors, and is perfectly possible, but not
  >> > implemented:
  >> >
  >> > http://d.puremagic.com/issues/show_bug.cgi?id=6082
  >>
  >> What was the resolution for the case when the constructor is a
 template?
  >> I think that's why IFTI doesn't work for structs and classes in C++.
  >> Although, I can't get the following to compile in D anyway (that old
 and
  >> annoying error message again! :p):
  >>
  >> Error: no property 'opCall' for type 'deneme.B'
  >>
  >> import std.conv;
  >>
  >> class B
  >> {
  >> string s;
  >>
  >> this(T)(T t) // <-- Is the struct a template
  >> // or the constructor a template?
  >
  > The constructor it is, and B is a class, not a struct.

 Ah! Thanks!

 So today the following works; and not B, but the constructor is a template:

 import std.conv;

 struct B
 {
      string s;

      this(T)(T t)       // <-- constructor is a template
      {
          s = to!string(t);
      }
 }

 void main()
 {
      auto b0 = B(42);       // construct with int
      assert(b0.s == "42");

      auto b1 = B(1.5);      // construct with double
      assert(b1.s == "1.5");
 }

 With the proposed feature, the struct would be a template.

With the proposed feature still the constructor would be a template. The proposed feature is just that IFTI for constructors should be able to deduce the parameters for the enclosing struct/class template additionally to just its own parameters.
  >> {
  >> s = to!string(t);
  >> }
  >> }
  >>
  >> void main()
  >> {
  >> auto b0 = B(42);
  >> }
  >>
  >> I wasn't around when the static opCall() was designed but it is
 probably
  >> the very first thing that bugged me about D. :) I want B(42) to be
  >> object construction, not opCall(), which is not even defined.
  >>
  >> Ali
  >>
  >
  > Why? What useful semantics would that have for classes?

 I am not sure but the point is, if function templates provide IFTI, then
 because of being functions the constructors could provide IFTI as well,
 as it does for the struct B above.

 As an aside, I don't know why it is not the same with classes. I hope I
 am not again making an error in the following code. I have replaced
 'struct' with 'class' and inserted two 'new' keywords:

 import std.conv;

 class B
 {
      string s;

      this(T)(T t)
      {
          s = to!string(t);
      }
 }

 void main()
 {
      auto b0 = new B(42);   // line 61459
      assert(b0.s == "42");

      auto b1 = new B(1.5);  // line 61462
      assert(b1.s == "1.5");
 }

 The compiler says:

 deneme.d(61459): Error: no constructor for B
 deneme.d(61462): Error: no constructor for B
 deneme.d(61462): Warning: statement is not reachable

 Ali

This seems to be a bug.
Feb 17 2012