www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template help - MultiAccess

reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
  I'm making a template to handle multiple accesses to the same 
name. In making my compression algorithm (and BitArray) I realize 
how much code is going into just forward referencing to things 
based on certain states.

  I have the following head template (there's about 5 total with 
how I see it):


   template multiAccess(Type, string name, string attributes,
           choice, bool read, bool write, T ...) {
     static assert(T.length % 2 == 0,
           "Must be in pairs, AccessName & matching Value");
     //eponymous enum
     enum multiAccess =
           multiAccessFunctions!(Type, name, attributes, choice, 
read, write, T);
   }


I'm calling it with:
   int choice;
   int a = 100;
   int b = 200;
   int c = 300;

   writeln(multiAccess!(int, "test", " safe nothrow pure", choice, 
true, true,
     a, 0,
     b, 1,
     c, 2));

  And I'm getting the error of:

Error: template instance multiAccess!(int, "test", " safe nothrow 
pure", choice, true, true, a, 0, b, 1, c, 2) multiAccess!(int, 
"test", " safe nothrow pure", choice, true, true, a, 0, b, 1, c, 
2) does not match template declaration multiAccess(Type, string 
name, string attributes, choice, bool read, bool write, T...)

  Maybe something obvious but I'm not seeing it.
Jan 08 2013
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/8/13, Era Scarecrow <rtcvb32 yahoo.com> wrote:
    template multiAccess(Type, string name, string attributes,
            choice, bool read, bool write, T ...) {
 I'm calling it with:
    int choice;
    writeln(multiAccess!(int, "test", " safe nothrow pure", choice,
 true, true,
'choice' is not a type, use: template multiAccess(Type, string name, string attributes, alias choice, bool read, bool write, T ...) {
Jan 08 2013
prev sibling next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 8 January 2013 at 19:58:20 UTC, Era Scarecrow wrote:
  I'm making a template to handle multiple accesses to the same 
 name. In making my compression algorithm (and BitArray) I 
 realize how much code is going into just forward referencing to 
 things based on certain states.

  I have the following head template (there's about 5 total with 
 how I see it):


   template multiAccess(Type, string name, string attributes,
           choice, bool read, bool write, T ...) {
     static assert(T.length % 2 == 0,
           "Must be in pairs, AccessName & matching Value");
     //eponymous enum
     enum multiAccess =
           multiAccessFunctions!(Type, name, attributes, choice, 
 read, write, T);
   }


 I'm calling it with:
   int choice;
   int a = 100;
   int b = 200;
   int c = 300;

   writeln(multiAccess!(int, "test", " safe nothrow pure", 
 choice, true, true,
     a, 0,
     b, 1,
     c, 2));

  And I'm getting the error of:

 Error: template instance multiAccess!(int, "test", " safe 
 nothrow pure", choice, true, true, a, 0, b, 1, c, 2) 
 multiAccess!(int, "test", " safe nothrow pure", choice, true, 
 true, a, 0, b, 1, c, 2) does not match template declaration 
 multiAccess(Type, string name, string attributes, choice, bool 
 read, bool write, T...)

  Maybe something obvious but I'm not seeing it.
You appear to want "choice" to represent a value, rather than a type. Declare it as "int choice" or "alias choice" Not that with "int choice", you'll get a compiler error because it isn't a compile constant. I'm not really sure about how "alias" works, but that's the source of your problem.
Jan 08 2013
parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 8 January 2013 at 20:07:29 UTC, monarch_dodra wrote:
 You appear to want "choice" to represent a value, rather than a 
 type.

 Declare it as "int choice" or "alias choice"

 Not that with "int choice", you'll get a compiler error because 
 it isn't a compile constant. I'm not really sure about how 
 "alias" works, but that's the source of your problem.
Ahh. I changed it and instantly it compiles. I never quite did understand alias for templates, but now I think I have a better grasp.
Jan 08 2013
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Tue, Jan 8, 2013 at 9:14 PM, Era Scarecrow <rtcvb32 yahoo.com> wrote:

 On Tuesday, 8 January 2013 at 20:07:29 UTC, monarch_dodra wrote:

 You appear to want "choice" to represent a value, rather than a type.

 Declare it as "int choice" or "alias choice"

 Not that with "int choice", you'll get a compiler error because it isn't
 a compile constant. I'm not really sure about how "alias" works, but that's
 the source of your problem.
Ahh. I changed it and instantly it compiles. I never quite did understand alias for templates, but now I think I have a better grasp.
alias for templates gives you a 'symbol' parameter: you can pass any identifier to it: variable, user-defined types, module names... Not built-in types (int,...) which are keywords and *not* valid identifiers. A single identifier in a template parameter list (usually marked with UpperCase) denotes a type.
Jan 08 2013
parent "bearophile" <bearophileHUGS lycos.com> writes:
Philippe Sigaud:

 alias for templates gives you a 'symbol' parameter: you can 
 pass any
 identifier to it: variable, user-defined types, module names...
 Not built-in types (int,...) which are keywords and *not* valid 
 identifiers.
I remember some persons have asked for built-in types too to work in this case. Bye, bearophile
Jan 08 2013
prev sibling parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
  Well after getting the alias problem out of the way, I have a 
working template. If anyone cares to look it over and critique 
it. I'll consider adding it to phobos (assuming I didn't miss 
something similiar), although I am not sure where it would be 
added as it doesn't quite qualify for std.traits, std.bitmanip, 
maybe std.functional?

  
https://github.com/rtcvb32/Side-Projects/blob/master/multiaccess.d
Jan 08 2013
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Tue, Jan 8, 2013 at 10:37 PM, Era Scarecrow <rtcvb32 yahoo.com> wrote:
  Well after getting the alias problem out of the way, I have a working te=
mplate. If anyone cares to look it over and critique it. I'll consider addi= ng it to phobos (assuming I didn't miss something similiar), although I am = not sure where it would be added as it doesn't quite qualify for std.traits= , std.bitmanip, maybe std.functional?
  https://github.com/rtcvb32/Side-Projects/blob/master/multiaccess.d
Some comments: mixin(multiAccess!( int, //return type "test", //function call/name "nothrow", //attributes choice, //variable/call that determines which to call true, //make read function true, //make write function a, false, //choose a if 'choice' is false b, true)); //choose b if 'choice' is true The 'int,' part is not necessary: names a and b have a type, you can determine int from CommonType!(typeof(a),typeof(b)). One less field for your user. Concerning the 'true'/'false' parts for the read/write function: I'm not sure they are necessary. If you want your host to be a multi access struct, you sure want people to access the fields... Should you still choose to let these parameters, please use two enums: enum ReadAccess { no, yes } and WriteAccess {no, yes }. This makes for a more explicit code when calling the template: ... choice, ReadAccess.yes, WriteAccess.no, ... For the (a, true) pairs, I'd invert the arguments: first the value, then the effect (in this case, which field to access). As for the global usefulness of your mixin, I don't know. I never felt a need for such a construction, so I can't comment much more on it.
Jan 08 2013
next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 8 January 2013 at 23:17:46 UTC, Philippe Sigaud wrote:
 On Tue, Jan 8, 2013 at 10:37 PM, Era Scarecrow wrote:
 Some comments:

 mixin(multiAccess!(
                 int,        //return type
                 "test",     //function call/name
                 "nothrow",  //attributes
                 choice,     //variable/call that determines 
 which to call
                 true,       //make read function
                 true,       //make write function
                 a, false,   //choose a if 'choice' is false
                 b, true));  //choose b if 'choice' is true

 The 'int,' part is not necessary: names a and b have a type, 
 you can determine int from CommonType!(typeof(a),typeof(b)).
 One less field for your user.
Maybe not. In other use cases the variables may be in quoted allowing you to specify it's within other structs (or functions), same with the 'choice'. I'm currently working on modifying my code to do that very thing, so a return type may very well still be required.
 Concerning the 'true'/'false' parts for the read/write 
 function: I'm not sure they are necessary. If you want your 
 host to be a multi access struct, you sure want people to 
 access the fields...
 Should you still choose to let these parameters, please use two 
 enums:
 enum ReadAccess { no, yes } and WriteAccess { no, yes }.
 This makes for a more explicit code when calling the template:
True, and most likely I will move to enums, but I needed a quick and easy way to tell them apart; I'm sure there's cases where you only want to write or read from particular variables (empty for example?). I'd probably condense it into a single enum, being something like: enum Access { read, write, readWrite }.
 For the (a, true) pairs, I'd invert the arguments: first the 
 value, then the effect (in this case, which field to access).
If it makes more sense to do so then I have no objection. More likely they'll be ints or enums. in my more complex unittest it uses: a, 0, b, 1, c, 2 so would this look better? 0, a, 1, b, 2, c Somehow seems backwards to me, I almost think of them more as a=0, b=1, c=2 type of thing; vs 0=a, 1=b, 2=c, but with enums then a=one, b=two, c=three vs one=a, two=b, three=c; both look kinda natural.
 As for the global usefulness of your mixin, I don't know. I 
 never felt a need for such a construction, so I can't comment 
 much more on it.
Global use is very unlikely (but not impossible) as that type of access seems to be shunned from the bad code it generated. Much less so now. The only problem with making it global is the reading function having const, as the compiler complains about requiring 'this'.
Jan 08 2013
prev sibling parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 8 January 2013 at 23:17:46 UTC, Philippe Sigaud wrote:
 The 'int,' part is not necessary: names a and b have a type, 
 you can determine int from CommonType!(typeof(a),typeof(b)). 
 One less field for your user.
Here's a working example, although my updated code hasn't been synced yet. Naming isn't used but is small enough you don't really need them. struct S { struct X {int d, e;} X x; mixin(multiAccess!(int, "maxX", " safe pure nothrow", "x.d > x.e", true, true, //choice, read/write "x.d", true, "x.e", false)); } unittest { S s; s.x.d = 5; s.x.e = 10; //maxX returns and references ONLY the larger of the two. assert(s.maxX == 10); s.maxX = 15; assert(s.maxX == 15); assert(s.x.d == 5 && s.x.e == 15); } In this case, d & e are both strings, and returning a string wouldn't work (with an int). Choice can be replaced with a function (or lambda?). I think it's clear to see how these can be used.
Jan 08 2013
parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
  Updated code, now accepts quoted strings for choice & variables.

  
https://github.com/rtcvb32/Side-Projects/blob/master/multiaccess.d
Jan 08 2013