www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Parameterized Structs

reply Peter Lundgren <lundgrpb rose-hulman.edu> writes:
Where can I go to learn about parameterized structs? I can't seem to find any
literature on the subject. In particular, what are you allowed to use as a
parameter? I would like to define a struct like so:

struct MyStruct(T, T[] a) {
    ...
}

but I receive the following error:

Error: arithmetic/string type expected for value-parameter, not T[]

Are arrays not allowed?
Mar 02 2011
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday 02 March 2011 20:56:41 Peter Lundgren wrote:
 Where can I go to learn about parameterized structs? I can't seem to find
 any literature on the subject. In particular, what are you allowed to use
 as a parameter? I would like to define a struct like so:
 
 struct MyStruct(T, T[] a) {
     ...
 }
 
 but I receive the following error:
 
 Error: arithmetic/string type expected for value-parameter, not T[]
 
 Are arrays not allowed?

I've never tried anything but arithmetic types and strings for a template value parameter, so I don't know, but the error message would certainly imply that it's not allowed. Regardless, its value would have to be known at compile time. - Jonathan M Davis
Mar 02 2011
prev sibling next sibling parent reply Bekenn <leaveme alone.com> writes:
On 3/2/2011 8:56 PM, Peter Lundgren wrote:
 Where can I go to learn about parameterized structs? I can't seem to find any
 literature on the subject. In particular, what are you allowed to use as a
 parameter? I would like to define a struct like so:

 struct MyStruct(T, T[] a) {
      ...
 }

 but I receive the following error:

 Error: arithmetic/string type expected for value-parameter, not T[]

 Are arrays not allowed?

This compiles: struct MyStruct(T : T[], T a) { T A = a.dup; } ...but I have yet to figure out how to properly invoke it.
Mar 02 2011
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 03 Mar 2011 00:45:05 -0500, Bekenn <leaveme alone.com> wrote:

 On 3/2/2011 8:56 PM, Peter Lundgren wrote:
 Where can I go to learn about parameterized structs? I can't seem to  
 find any
 literature on the subject. In particular, what are you allowed to use  
 as a
 parameter? I would like to define a struct like so:

 struct MyStruct(T, T[] a) {
      ...
 }

 but I receive the following error:

 Error: arithmetic/string type expected for value-parameter, not T[]

 Are arrays not allowed?

This compiles: struct MyStruct(T : T[], T a) { T A = a.dup; } ...but I have yet to figure out how to properly invoke it.

warning to all template novices -- a template compiling simply means it *PARSES*. You have to instantiate it, in order to verify it is correct. The compiler cannot possibly know the semantic meaning of a template without knowing what the parameters are. I would expect your struct to never instantiate properly, because a.dup is not a valid static initializer. -Steve
Mar 03 2011
prev sibling next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/02/2011 08:56 PM, Peter Lundgren wrote:
 Where can I go to learn about parameterized structs? I can't seem to find any
 literature on the subject. In particular, what are you allowed to use as a
 parameter? I would like to define a struct like so:

 struct MyStruct(T, T[] a) {
      ...
 }

 but I receive the following error:

 Error: arithmetic/string type expected for value-parameter, not T[]

 Are arrays not allowed?

Are you trying to parametrize by the type of the container or just trying to use an array of a specified type? (As opposed to say, a linked list of the specified type?) If the former, it's simple. And the simplest thing is to just use an array in the implementation: struct S(T) { T[] a; void foo(T element) { /* Just use like an array */ a ~= element; a[0] = element; } } void main() { auto s = S!double(); s.foo(1.5); } If you want to use a different container of the specified T, then a second template parameter can be used. This one uses an array as the default one: class SomeContainer {} struct S(T, Cont = T[]) { Cont a; void foo(T element) { /* This time the use must match the allowed container types */ } } void main() { auto s = S!(double, SomeContainer)(); s.foo(1.5); } I would recommend pulling information out ;) of this page: http://digitalmars.com/d/2.0/template.html "Template Alias Parameters" is very different after C++ and can be very powerful: http://digitalmars.com/d/2.0/template.html#TemplateAliasParameter Ali
Mar 02 2011
next sibling parent reply Peter Lundgren <lundgrpb rose-hulman.edu> writes:
== Quote from Ali Çehreli (acehreli yahoo.com)'s article
 On 03/02/2011 08:56 PM, Peter Lundgren wrote:
 Where can I go to learn about parameterized structs? I can't seem to find any
 literature on the subject. In particular, what are you allowed to use as a
 parameter? I would like to define a struct like so:

 struct MyStruct(T, T[] a) {
      ...
 }

 but I receive the following error:

 Error: arithmetic/string type expected for value-parameter, not T[]

 Are arrays not allowed?

trying to use an array of a specified type? (As opposed to say, a linked list of the specified type?) If the former, it's simple. And the simplest thing is to just use an array in the implementation: struct S(T) { T[] a; void foo(T element) { /* Just use like an array */ a ~= element; a[0] = element; } } void main() { auto s = S!double(); s.foo(1.5); } If you want to use a different container of the specified T, then a second template parameter can be used. This one uses an array as the default one: class SomeContainer {} struct S(T, Cont = T[]) { Cont a; void foo(T element) { /* This time the use must match the allowed container types */ } } void main() { auto s = S!(double, SomeContainer)(); s.foo(1.5); } I would recommend pulling information out ;) of this page: http://digitalmars.com/d/2.0/template.html "Template Alias Parameters" is very different after C++ and can be very powerful: http://digitalmars.com/d/2.0/template.html#TemplateAliasParameter Ali

I'm using this for an alternative implementation of a string, if you will. Where T is the type of a single character and a would be the alphabet (an array of allowed characters). The rest of the implementation of the struct would, of course, depend upon the provided alphabet. I guess value parameters can't be arbitrary types. I can probably get by with using a string for my alphabet just fine, it just seemed an arbitrary limitation. Why accept only arrays of characters when the code will be the same for any type?
Mar 02 2011
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/02/2011 11:11 PM, Peter Lundgren wrote:
 == Quote from Ali Çehreli (acehreli yahoo.com)'s article
 On 03/02/2011 08:56 PM, Peter Lundgren wrote:
 Where can I go to learn about parameterized structs? I can't seem 



 literature on the subject. In particular, what are you allowed to 



 parameter? I would like to define a struct like so:

 struct MyStruct(T, T[] a) {
       ...
 }

 but I receive the following error:

 Error: arithmetic/string type expected for value-parameter, not T[]

 Are arrays not allowed?

trying to use an array of a specified type? (As opposed to say, a linked list of the specified type?) If the former, it's simple. And the simplest thing is to just use an array in the implementation: struct S(T) { T[] a; void foo(T element) { /* Just use like an array */ a ~= element; a[0] = element; } } void main() { auto s = S!double(); s.foo(1.5); } If you want to use a different container of the specified T, then a second template parameter can be used. This one uses an array as the default one: class SomeContainer {} struct S(T, Cont = T[]) { Cont a; void foo(T element) { /* This time the use must match the allowed container types */ } } void main() { auto s = S!(double, SomeContainer)(); s.foo(1.5); } I would recommend pulling information out ;) of this page: http://digitalmars.com/d/2.0/template.html "Template Alias Parameters" is very different after C++ and can be very powerful: http://digitalmars.com/d/2.0/template.html#TemplateAliasParameter Ali

I'm using this for an alternative implementation of a string, if you

 is the type of a single character and a would be the alphabet (an 

 characters). The rest of the implementation of the struct would, of 

 upon the provided alphabet.

 I guess value parameters can't be arbitrary types. I can probably get 

 using a string for my alphabet just fine, it just seemed an arbitrary 

 Why accept only arrays of characters when the code will be the same 

I think the SomeContainer example above should work then: it is not "arrays of characters". T[] was just the default implementation. If SomeContainer is templatized, then I think this is what you want: /* A templatized container */ class SomeContainer(T) { /* having container functions */ void add(T element) {} T access(size_t index) { return T.init; } } /* This is your "alternative implementation of a string". Can use any * container type, the default is array of Ts */ struct S(T, Cont = T[]) { Cont a; void foo(T element) { /* here the use must match the allowed container types */ } } void main() { /* We are instantiating it with * * double as the element type * SomeContainer!double as the container type */ auto s = S!(double, SomeContainer!double)(); s.foo(1.5); } But we can make it better, because 'double' and 'SomeContainer!double' repeat "double". Here the alias template parameters are handy: struct S(T, alias ContType) // <-- alias { ContType!T a; // <-- ContType!T instead of just Cont void foo(T element) { /* here the use must match the allowed container types */ } } The second parameter is an alias template parameter. (I had to drop the default value; I think we can use Array!T there, but I haven't bothered to test.) Now the use is easier and less error prone, because 'double' need not be repeated: auto s = S!(double, SomeContainer)(); Ali
Mar 02 2011
parent reply Peter Lundgren <lundgrpb rose-hulman.edu> writes:
== Quote from Ali Çehreli (acehreli yahoo.com)'s article
 On 03/02/2011 11:11 PM, Peter Lundgren wrote:
  > == Quote from Ali Çehreli (acehreli yahoo.com)'s article
  >> On 03/02/2011 08:56 PM, Peter Lundgren wrote:
  >>> Where can I go to learn about parameterized structs? I can't seem
 to find any
  >>> literature on the subject. In particular, what are you allowed to
 use as a
  >>> parameter? I would like to define a struct like so:
  >>>
  >>> struct MyStruct(T, T[] a) {
  >>>       ...
  >>> }
  >>>
  >>> but I receive the following error:
  >>>
  >>> Error: arithmetic/string type expected for value-parameter, not T[]
  >>>
  >>> Are arrays not allowed?
  >> Are you trying to parametrize by the type of the container or just
  >> trying to use an array of a specified type? (As opposed to say, a linked
  >> list of the specified type?)
  >> If the former, it's simple. And the simplest thing is to just use an
  >> array in the implementation:
  >> struct S(T)
  >> {
  >>       T[] a;
  >>       void foo(T element)
  >>       {
  >>           /* Just use like an array */
  >>           a ~= element;
  >>           a[0] = element;
  >>       }
  >> }
  >> void main()
  >> {
  >>       auto s = S!double();
  >>       s.foo(1.5);
  >> }
  >> If you want to use a different container of the specified T, then a
  >> second template parameter can be used. This one uses an array as the
  >> default one:
  >> class SomeContainer
  >> {}
  >> struct S(T, Cont = T[])
  >> {
  >>       Cont a;
  >>       void foo(T element)
  >>       {
  >>           /* This time the use must match the allowed container types */
  >>       }
  >> }
  >> void main()
  >> {
  >>       auto s = S!(double, SomeContainer)();
  >>       s.foo(1.5);
  >> }
  >> I would recommend pulling information out ;) of this page:
  >>     http://digitalmars.com/d/2.0/template.html
  >> "Template Alias Parameters" is very different after C++ and can be very
  >> powerful:
  >>     http://digitalmars.com/d/2.0/template.html#TemplateAliasParameter
  >> Ali
  >
  > I'm using this for an alternative implementation of a string, if you
 will. Where T
  > is the type of a single character and a would be the alphabet (an
 array of allowed
  > characters). The rest of the implementation of the struct would, of
 course, depend
  > upon the provided alphabet.
  >
  > I guess value parameters can't be arbitrary types. I can probably get
 by with
  > using a string for my alphabet just fine, it just seemed an arbitrary
 limitation.
  > Why accept only arrays of characters when the code will be the same
 for any type?
 I think the SomeContainer example above should work then: it is not
 "arrays of characters". T[] was just the default implementation. If
 SomeContainer is templatized, then I think this is what you want:
 /* A templatized container */
 class SomeContainer(T)
 {
      /* having container functions */
      void add(T element)
      {}
      T access(size_t index)
      {
          return T.init;
      }
 }
 /* This is your "alternative implementation of a string". Can use any
   * container type, the default is array of Ts */
 struct S(T, Cont = T[])
 {
      Cont a;
      void foo(T element)
      {
          /* here the use must match the allowed container types */
      }
 }
 void main()
 {
      /* We are instantiating it with
       *
       *   double as the element type
       *   SomeContainer!double as the container type
       */
      auto s = S!(double, SomeContainer!double)();
      s.foo(1.5);
 }
 But we can make it better, because 'double' and 'SomeContainer!double'
 repeat "double". Here the alias template parameters are handy:
 struct S(T, alias ContType)  // <-- alias
 {
      ContType!T a;            // <-- ContType!T instead of just Cont
      void foo(T element)
      {
          /* here the use must match the allowed container types */
      }
 }
 The second parameter is an alias template parameter. (I had to drop the
 default value; I think we can use Array!T there, but I haven't bothered
 to test.)
 Now the use is easier and less error prone, because 'double' need not be
 repeated:
      auto s = S!(double, SomeContainer)();
 Ali

That's closer, except I want to pass a value parameter (specifically, some compile time instance of SomeContainer) instead of a type parameter, but that doesn't look like it's supported.
Mar 03 2011
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/03/2011 12:21 AM, Peter Lundgren wrote:

   >>  On 03/02/2011 08:56 PM, Peter Lundgren wrote:


   >>>  struct MyStruct(T, T[] a) {
   >>>        ...
   >>>  }
   >>>
   >>>  but I receive the following error:
   >>>
   >>>  Error: arithmetic/string type expected for value-parameter, 


...
 That's closer, except I want to pass a value parameter (specifically, 

 time instance of SomeContainer) instead of a type parameter, but that 

 like it's supported.

I finally get it! :) Yes, there are limitations for template value parameters. The spec at http://digitalmars.com/d/2.0/template.html#TemplateValueParameter says: <quote> Template value parameter types can be any type which can be statically initialized at compile time, and the value argument can be any expression which can be evaluated at compile time. This includes integers, floating point types, and strings. </quote> Ali
Mar 03 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Ali Çehreli:

 <quote>
 Template value parameter types can be any type which can be statically 
 initialized at compile time, and the value argument can be any 
 expression which can be evaluated at compile time. This includes 
 integers, floating point types, and strings.
 </quote>

I have needed arrays as template specialization arguments few times (I have used alias to solve the problem). Allowing strings but not arrays is one limitation that I don't understand. Bye, bearophile
Mar 03 2011
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/03/2011 03:25 AM, bearophile wrote:
 Ali Çehreli:

 <quote>
 Template value parameter types can be any type which can be statically
 initialized at compile time, and the value argument can be any
 expression which can be evaluated at compile time. This includes
 integers, floating point types, and strings.
 </quote>

I have needed arrays as template specialization arguments few times (I have used alias to solve the problem). Allowing strings but not arrays is one limitation that I don't understand.

And I thought that pointers to statically known instances could be a workaround, but no pointers allowed. (As an aside, C++ allows pointer template parameters.) Ali
 Bye,
 bearophile

Mar 03 2011
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Thu, 03 Mar 2011 08:36:41 -0000, Ali =C7ehreli <acehreli yahoo.com> w=
rote:

 On 03/03/2011 12:21 AM, Peter Lundgren wrote:

  >>   >>  On 03/02/2011 08:56 PM, Peter Lundgren wrote:

  >>   >>>  struct MyStruct(T, T[] a) {
  >>   >>>        ...
  >>   >>>  }
  >>   >>>
  >>   >>>  but I receive the following error:
  >>   >>>
  >>   >>>  Error: arithmetic/string type expected for value-parameter,=

 not T[]

 ...

  > That's closer, except I want to pass a value parameter (specificall=

 some compile
  > time instance of SomeContainer) instead of a type parameter, but th=

 doesn't look
  > like it's supported.

 I finally get it! :)

 Yes, there are limitations for template value parameters. The spec at

    http://digitalmars.com/d/2.0/template.html#TemplateValueParameter

 says:

 <quote>
 Template value parameter types can be any type which can be statically=

 initialized at compile time, and the value argument can be any  =

 expression which can be evaluated at compile time. This includes  =

 integers, floating point types, and strings.
 </quote>

So.. you could pass your alphabet in a string, then split it into = characters internally. For example. R
Mar 03 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 03 Mar 2011 06:25:36 -0500, bearophile <bearophileHUGS lycos.com>  
wrote:

 Ali Çehreli:

 <quote>
 Template value parameter types can be any type which can be statically
 initialized at compile time, and the value argument can be any
 expression which can be evaluated at compile time. This includes
 integers, floating point types, and strings.
 </quote>

I have needed arrays as template specialization arguments few times (I have used alias to solve the problem). Allowing strings but not arrays is one limitation that I don't understand.

An array literal is a runtime-initialized entity, much to the chagrin of Don and others (like myself). There have been several pushes to try and get Walter to change array literals to immutable compile-time things, but it has so far not been accepted. -Steve
Mar 03 2011
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On 03/03/2011 05:56 AM, Peter Lundgren wrote:
 Where can I go to learn about parameterized structs? I can't seem to find any
 literature on the subject. In particular, what are you allowed to use as a
 parameter? I would like to define a struct like so:

 struct MyStruct(T, T[] a) {
      ...
 }

 but I receive the following error:

 Error: arithmetic/string type expected for value-parameter, not T[]

 Are arrays not allowed?

Aside the error, I find this a bit strange. Do you really mean that /both/ a type T and an element of type T[] are /template/ parameters? Would you show your case? I expect (but may be wrong, indeed) something like this: struct MyStruct(T) { T[] a; ... } or maybe: struct MyStruct(T) { static T[] a = [...]; ... } Denis -- _________________ vita es estrany spir.wikidot.com
Mar 03 2011
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On 03/03/2011 12:25 PM, bearophile wrote:
 Ali Çehreli:

 <quote>
 Template value parameter types can be any type which can be statically
 initialized at compile time, and the value argument can be any
 expression which can be evaluated at compile time. This includes
 integers, floating point types, and strings.
 </quote>

I have needed arrays as template specialization arguments few times (I have used alias to solve the problem). Allowing strings but not arrays is one limitation that I don't understand. Bye, bearophile

That may be because strings are immutable? Denis -- _________________ vita es estrany spir.wikidot.com
Mar 03 2011
prev sibling parent reply spir <denis.spir gmail.com> writes:
On 03/03/2011 05:56 AM, Peter Lundgren wrote:
 Where can I go to learn about parameterized structs? I can't seem to find any
 literature on the subject. In particular, what are you allowed to use as a
 parameter? I would like to define a struct like so:

 struct MyStruct(T, T[] a) {
      ...
 }

 but I receive the following error:

 Error: arithmetic/string type expected for value-parameter, not T[]

 Are arrays not allowed?

Finally managed to do it, I guess :-) ============================ bool[E] set (E : E[]) (E[] elements) { bool[E] set; foreach (element ; elements) set[element] = true; return set; } struct String (C : C[], alias characters) { alias typeof(characters) S; //~ alias ElementType!S C; // BUG! returns dchar bool[C] klass = null; private C[] s; this (S s) { this.klass = set!S(characters); this.def(s); } void def (S s = null) { if (s.length == 0) { this.s = s; return; } foreach (ch ; s) { if (ch !in this.klass) { auto message = format( "'%s' not in allowed class of characters" , ch); throw new Exception(message); } } this.s = s; } string toString () { return format("String!(%s,\"%s\")(\"%s\")", S.stringof, characters, this.s); } } unittest { auto s = String!(string, "abcde")(""); writeln(s); s.def("eca"); writeln(s); s = String!(string, "abcde")("ace"); writeln(s); s = String!(string, "abcde")("fgh"); // --> error writeln(s); } ============================ Some notes: * set is here to speed up character lookup among allowed klass (else, O(N) in array). * C: C[] in struct template is redondant, since C[] is typeof(characters). It is only needed to declare the set 'klass', because of a bug: ElementType!string returns dchar!!! Thus, it is would not be possible, I guess, to declare klass's type in the struct definition. * You must pass an init string (even if "") to call this() and construct klass. Because of another bug: there cannot be parameter-less constructors for structs. Also, set cannot be defined on toplevel of the struct def auto klass = set!S(characters); because it's not a constant according to dmd. (It is, in fact). Thus, I guess we must construct it inside this(). Denis -- _________________ vita es estrany spir.wikidot.com
Mar 03 2011
parent bearophile <bearophileHUGS lycos.com> writes:
spir:

 because of a bug: ElementType!string 
 returns dchar!!! Thus, it is would not be possible, I guess, to declare
klass's 
 type in the struct definition.
 
 * You must pass an init string (even if "") to call this() and construct
klass. 
 Because of another bug: there cannot be parameter-less constructors for 
 structs.

I think those two are not bugs. Bye, bearophile
Mar 03 2011