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.

Reply via email to