template parameters

Charles Hixson charleshixsn at earthlink.net
Thu Sep 2 21:28:23 UTC 2021


Thanks.  See below for what I did.

On 8/29/21 5:05 PM, Ali Çehreli via Digitalmars-d-learn wrote:
> On 8/29/21 3:31 PM, Charles Hixson wrote:
> > Thanks.  I going to have to study:
> >
> > enum supportsCall = isIntegral!(typeof(T.init.%s()));
> >
> >
> > for awhile to make any sense of that, but it looks like just what I was
> > looking for.
>
> Trying to explain with comments:
>
> // This is an eponymous template because it contains
> // a symbol that's the same as the name of this template.
> // And that symbol is 'supportsCall'. So, this template
> // will be whatever that symbol is. (In this case, it
> // will be a compile-time know entity: 'enum bool'.)
>
> template supportsCall(T, string func) {
>   import std.format : format;
>   import std.traits : isIntegral;
>
>   // This is a string expression we will mix-in below.
>   enum expr = format!q{
>     enum supportsCall = isIntegral!(typeof(T.init.%s()));
>   }(func);
>
>   // The above expression will be the following e.g.
>   // for 'int' and for "ndx":
>   //
>   //   enum supportsCall = isIntegral!(typeof(int.init.ndx()));
>   //
>   // So, it's determining whether the typeof the expression
>   // int.init.ndx() is an integral.
>   //
>   // 'supportsCall' is a bool, which I could have made explicit:
>   //
>   //   enum bool supportsCall = [...]
>   //
>   // You can prove it for yourself by "printing" the expression
>   // at compile time:
>
>   pragma(msg, expr);
>
>   // Here is where we mix-in the expression into this template's
>   // definition.
>
>   mixin (expr);
> }
>
> Then the whole template can be used as a compile-time bool value.
>
> Ali
>
I'm going to need to save that for the future.  I ran into errors in 
other sections.  I suspect that a general form would require static if 
tests in numerous routines.  Anyway, if you're interested this is what I 
ended up with. (I think it's error free, but not all paths have been 
tested.)

import    std.algorithm : remove;
import    std.exception;
import    std.stdio;
import    std.traits : isIntegral;

import    utils;    //    this is for my randomized integer code based 
on time:  rndT

/**    An Associative Array with some Randomization and Linear features.
  * Note:  This is done in a simplified and not too generalized fashion 
so that I don't need to
  *         figure out template parameters at the moment.  It should be 
redone later, when my mastery
  *         is better.  The current version should work for classes and 
structs that have a function
  *         int T.ndx() that returns a unique id.  That id (called the 
key) is used as an AA index
  *         to find the instance, with duplicates not being allowed.    */
class    AARL2 (T)
{    /**    The associative array of cells, with the index as the key.    */
     T[int]    aa;
     /**    A linear array of cell key values.  This is ordered by the 
order in which they were
      * inserted rather than by value.    */
     int[]    rl;

     /**    Create an AARL from an array of cells.  The array must have 
no entries with duplicate
      * key values (i.e. cell.ndx).  Currently this throws an 
exception.  Consider how it could
      * be handled more gracefully.    */
     this (T[] inp)
     {    foreach (T c; inp)
         {    int    key    =    c.ndx;
             enforce (key !in aa, "Attempt to insert a key already 
present.");
             aa[key]    =    c;
             rl    ~=    key;
         }
     }
     this ()    {}

     /**    Access members by serial position of key.  (Not the value of 
the key!)    */
     T    at (int i)
     in    {    assert (i >= 0 && i < rl.length, "Index outside 
bounds");    }
     body
     {    int    key    =    rl[i];
         return    aa[key];
     }

     /**    This is a read-only count of number of entries.    */
     long    length()    {    return    aa.length;    }

     bool opBinaryRight(string op)(int key) const
             if (op == "in")
     {    return    cast (bool)(key in aa);    }

     bool opBinaryRight(string op)(T c) const
             if (op == "in")
     {    return    cast (bool)(c.ndx in aa);    }

     /**    Allow the [] operator to retrieve instances by key value.    */
     T opIndex(int key)
     {    if    (key in aa)    return    aa[key];
         return    null;
     }

     /**    "append" an instance of T.    */
     void opOpAssign (string op)(T c)
//            if    (op == "~=" && isIntegral!(typeof(T.init.ndx())
             if    (op == "~")
     {    append (c);    }

     /**    "append" an instance of T.
      * Note:  I need a better response to an attempt to add 
duplicates.    */
     void    append (T c)
     {    if    (c is null)
         {    stderr.writeln ("Attempt to add a null T to the AARL 
rejected.");
             return;
         }
         int    key    =    c.ndx;
         if (key in aa)
         {    aa[key]    =    c;    }
         else
         {    aa[key]    =    c;
             rl    ~=    key;
         }
         return;
     }

     /**    Pop the most recently added T off the table.    */
     T    pop    ()
     {    if    (rl.length < 1)    return    null;
         T    c    =    aa[rl[cast(int)rl.length - 1]];
         aa.remove    (c.ndx);
         rl.length    -=    1;
         return    c;
     }

     /**    Pop a random cell off the table.    */
     T    popR()
     {    int    which    =    rndT(cast(int)rl.length);
         int    key    =    rl[which];
         assert    (key in aa, "AARL popR Logic error..1..but where?");
         T    c    =    aa[key];
         remove(c);
         return    c;
     }

     /**    Pop the most recently added Cells off the table until the 
key is found.  No value is returned.
      * Note:    The key value is left in the AARL.    */
     void    popUntil    (T c)
     in    {    assert (c.ndx in aa, "Trying to pop until a value is 
reached which isn't in the table.");    }
     body
     {    while (c.ndx != rl[rl.length - 1])
         {    pop();    }
     }

     /**    Push a cell onto the table.
      * Returns:    True if the push was successful.  False if either 
the item was null or one with
      *         the same key value was already in the table.    */
     bool    push (T c)
     {    if    (c is null)    return    false;
         if    (c.ndx in aa)    return    false;
         aa[c.ndx]    =    c;
         rl    ~=    c.ndx;
         return    true;
     }

     /**    Read the most recently pushed cell of the table.
      * WARNING:    No valid return value exists when the AARL is empty 
and T is not a class.
      *         Consider throwing an exception in that case. Currently 
that case is not handled.    */
     T    read()
     {    int    key    =    rl[rl.length - 1];
         assert    (key in aa, "AARL read Logic error...but where?");
         return    aa[key];
     }

     /**    Read a random cell of the table.
      * WARNING:    No valid return value exists when the AARL is empty 
and T is not a class.
      *         Consider throwing an exception in that case. Currently 
that case is not handled.    */
     T    readR()
     {    int    which    =    rndT(cast(int)rl.length);
         int    key    =    rl[which];
         assert    (key in aa, "AARL readR Logic error...but where?");
         return    aa[key];
     }

     /**    Remove a T from the table.
      * Returns:    True if successful, otherwise false.    */
     bool    remove (T c)
     {    if    (c is null)    return    false;
         return    removeKey (c.ndx);
     }

     /**    Remove the T whose key matches the given key from the table.
      * Returns:    True if successful, otherwise flase.    */
     bool    removeKey (int key)
     {    if    (key !in aa)    return    false;
         int    i    =    0;
         while (i < rl.length)
         {    if    (rl[i] == key)
             {    rl.remove(i);
                 aa.remove(key);
                 return    true;
             }
             i++;
         }
         assert (false, "Logic Error:  never come here");
     }
}
unittest
{    class AARLTest1
     {    int    ndx_;
         this    ()    {    ndx_    =    -1;    }
         this (int val)    {    ndx_    =    val;    }
         int    ndx()    {    return    ndx_;    }
     }
     //    some to test with a simple class
     AARLTest1[]    t1;
     for    (int i = 0; i < 10;    i++)    t1    ~=    new AARLTest1(i);
     //    t1t and instance of AARL2!AARLTest1 to run the tests on, 
i.e., "t1 tests"
     auto t1t    =    new AARL2!AARLTest1 (t1);
     assert (t1t.length == 10, "t1t.length != 10");
     t1t.push (new AARLTest1(11));
     assert (t1t.length == 11, "t1t.length != 11");
     //    t1ta the first auxillary variable for the testing.
     auto    t1ta    =    t1t.pop ();
     assert (t1t.length == 10, "t1t.length != 10");
     assert (t1ta.ndx() == 11, "t1ta.ndx() != 11");
     assert (t1ta !in t1t, "Oop1!  t1ta in t1t");
     //    t1tb the second auxillary variable for the testing.
     auto    t1tb    =    t1t.popR ();
     assert (t1t.length == 9, "t1t.length != 9");
     assert (t1tb !in t1t, "Oop2!  t1tb in t1t");
     t1ta    =    t1t.readR();
     assert (t1t.length == 9, "t1t.length != 9");
     assert (t1ta in t1t, "Oop3!  t1ta !in t1t");
     //    t1t.append (t1tb);
     t1t    ~=    t1tb;
     assert (t1t.length == 10, "t1t.length != 10");
     assert (t1tb in t1t, "Oop4!  t1tb !in t1t");
     t1t.removeKey(t1tb.ndx);
     assert (t1tb !in t1t, "Oop5!  removeKey failed.");
     t1t.remove (t1ta);
     assert (t1ta !in t1t, "Oop6!  remove failed.");
}

-- 
Javascript is what you use to allow third part programs you don't know anything about and doing you know not what to run on your computer.



More information about the Digitalmars-d-learn mailing list