www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Trouble with SList for generic Stack class

reply Mark <tigchelaarm mymacewan.ca> writes:
Hello,

I am trying to make a class that can accept any type as an 
argument.

Here is the class:


import std.container: SList;


class Stack {

   private SList!T list;
   private int _size;

   this(T)() {
     list = SList!T;
     _size = 0;
   }

   public void push(T)(T item) {
     list.insertFront(item);
     _size++;
   }

   public void pop(T)() {
     if(_size > 0){
       list.removeFront();
       _size--;
     }
   }

   public int getSize() { return _size; }

}


When I compile with dmd, I get this error:

Stack.d(6): Error: undefined identifier 'T'

That's on the line private SList!T list;

So the SList needs a type, but I can't give that type to it at 
that moment when I instantiate the class.
How do I over come this problem?

I might just write this again, using structs as a SLL. I might 
have similar issues with that as well.

Thanks,
Mark.
Jun 02
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Friday, 2 June 2017 at 22:21:07 UTC, Mark wrote:
 Hello,

 I am trying to make a class that can accept any type as an 
 argument.

 [...]
the stack class needs to be a template as well. This is not java ;)
Jun 02
parent reply Mark <tigchelaarm mymacewan.ca> writes:
Awesome. That worked.

On Friday, 2 June 2017 at 22:30:28 UTC, Stefan Koch wrote:
 On Friday, 2 June 2017 at 22:21:07 UTC, Mark wrote:
 Hello,

 I am trying to make a class that can accept any type as an 
 argument.

 [...]
the stack class needs to be a template as well. This is not java ;)
Stefan, what do you mean that it must be a template? Am I supposed to write template Struct(T) { class Stack { ... } }? I got that from programming in D, in the more templates section. This worked as well. What is the benefit of using the full syntax for templates? I'm new to templates, this is the first time I've ever used them. Thanks.
Jun 02
next sibling parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Fri, Jun 02, 2017 at 11:05:43PM +0000, Mark via Digitalmars-d-learn wrote:
[...]
 Stefan, what do you mean that it must be a template?
 
 Am I supposed to write template Struct(T) { class Stack { ... } }?
No, he means to turn class Stack into a template by adding a template parameter to it, like I suggested. In D, writing `class Stack(T) { ... }` is equivalent to writing: template Stack(T) { class Stack { ... } } It's the so-called eponymous template. The reason you need a template here is because, unlike Java, D does not do type erasure to achieve generic types. Full type information is preserved, so Stack!int and Stack!string represent distinct, incompatible types. T -- Never wrestle a pig. You both get covered in mud, and the pig likes it.
Jun 02
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
You've probably seen H. S. Teoh's answer but still... :)

On 06/02/2017 04:05 PM, Mark wrote:

 Am I supposed to write template Struct(T) { class Stack { ... } }?
Not necessary because in this case it's the same thing as class Stack(T) { // Don't templatize functions in here (in general) } However, you can templatize member functions as well if you want them to work with different types as well. For example, push() may work with any type that can be converted to T. class Stack(T) { private SList!T list; private int _size; this() { // Aside: No need to initialize members (in this case) // list = SList!T; // _size = 0; } public void push(T item) { list.insertFront(item); _size++; } public void pop() { if(_size > 0){ list.removeFront(); _size--; } } // Aside, length() is more idiomatic: public int length() { return _size; } } Ali
Jun 02
parent Mark <tigchelaarm mymacewan.ca> writes:
On Friday, 2 June 2017 at 23:34:14 UTC, Ali Çehreli wrote:
 You've probably seen H. S. Teoh's answer but still... :)

 ...

 Ali
Awesome, thanks everyone!
Jun 02
prev sibling parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Fri, Jun 02, 2017 at 10:21:07PM +0000, Mark via Digitalmars-d-learn wrote:
 Hello,
 
 I am trying to make a class that can accept any type as an argument.
 
 Here is the class:
 
 
 import std.container: SList;
 
 
 class Stack {
 
   private SList!T list;
   private int _size;
 
   this(T)() {
     list = SList!T;
     _size = 0;
   }
 
   public void push(T)(T item) {
     list.insertFront(item);
     _size++;
   }
 
   public void pop(T)() {
     if(_size > 0){
       list.removeFront();
       _size--;
     }
   }
 
   public int getSize() { return _size; }
 
 }
 
 
 When I compile with dmd, I get this error:
 
 Stack.d(6): Error: undefined identifier 'T'
 
 That's on the line private SList!T list;
Yes, because T is not specified when .list is declared. What you need to do is to put the template parameter on your class instead of your methods, something like this: class Stack(T) { private SList!T list; private int _size; this() { // N.B. no template parameter here list = SList!T; _size = 0; } public void push(T item) { // N.B. no template parameter here ... } ... } T -- What do you get if you drop a piano down a mineshaft? A flat minor.
Jun 02