www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - templating operators

reply Brad Roberts <braddr puremagic.com> writes:
I'm trying to create a container that will allow arbitrary key/value pair 
trees.  Box seems like a great start at supporting a 'holds anything' 
container.  The next step is making a smooth associative array of them.  
However, I don't seem to be able to create a nice templated opIndex or 
opIndexAssign.

-------- test.d ---------
import std.stdio;
import std.boxer;

class ValueContainer
{
    Box[char[]] _objects;

    template opIndex(T)
    {   
        T opIndex(char[] key)
        {   
            return unbox!(T)(_objects[key]);
        }
    }

    int opIndexAssign(int newValue, char[] key)
    {   
        _objects[key] = box(newValue);
        return 0;
    }

    template getValue(T)
    {   
        T getValue(char[] key)
        {   
            return unbox!(T)(_objects[key]);
        }
    }

    template insertKeyAndValue(T)
    {   
        void insertKeyAndValue(char[] key, T newValue)
        {   
            _objects[key] = box(newValue);
        }
    }
}

int main()
{
    ValueContainer values = new ValueContainer();

    values["int"] = 1;
    values.insertKeyAndValue!(int)("key", 10);

    writef("int: %s\n", values["int"]);
    writef("key: %s\n", values["key"]);
    writef("key: %s\n", values.getValue!(int)("key"));

    return 0;
}
---------------

$ dmd -g test.d                                                 
test.d(46): no [] operator overload for type test.ValueContainer
test.d(47): no [] operator overload for type test.ValueContainer
test.d(48): function expected before (), not 0 of type int

Any thoughts on how to make this work well?

Thanks,
Brad
Mar 02 2006
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 2 Mar 2006 18:01:07 -0800, Brad Roberts wrote:

 I'm trying to create a container that will allow arbitrary key/value pair 
 trees.  Box seems like a great start at supporting a 'holds anything' 
 container.  The next step is making a smooth associative array of them.  
 However, I don't seem to be able to create a nice templated opIndex or 
 opIndexAssign.
 
 -------- test.d ---------
 import std.stdio;
 import std.boxer;
 
 class ValueContainer
 {
     Box[char[]] _objects;
 
     template opIndex(T)
     {   
         T opIndex(char[] key)
         {   
             return unbox!(T)(_objects[key]);
         }
     }
 
     int opIndexAssign(int newValue, char[] key)
     {   
         _objects[key] = box(newValue);
         return 0;
     }
 
     template getValue(T)
     {   
         T getValue(char[] key)
         {   
             return unbox!(T)(_objects[key]);
         }
     }
 
     template insertKeyAndValue(T)
     {   
         void insertKeyAndValue(char[] key, T newValue)
         {   
             _objects[key] = box(newValue);
         }
     }
 }
 
 int main()
 {
     ValueContainer values = new ValueContainer();
 
     values["int"] = 1;
     values.insertKeyAndValue!(int)("key", 10);
 
     writef("int: %s\n", values["int"]);
     writef("key: %s\n", values["key"]);
     writef("key: %s\n", values.getValue!(int)("key"));
 
     return 0;
 }
 ---------------
 
 $ dmd -g test.d                                                 
 test.d(46): no [] operator overload for type test.ValueContainer
 test.d(47): no [] operator overload for type test.ValueContainer
 test.d(48): function expected before (), not 0 of type int
 
 Any thoughts on how to make this work well?

When I did this sort of thing I had to chnage the template name to be different to the member inside the template *and* I had to instantiate the member inside the class. The instantiation didn't surprise me but the naming conflict one did. Anyhow, replace ... template opIndex(T) { T opIndex(char[] key) { return unbox!(T)(_objects[key]); } } with ... template opIndex_T(T) { T opIndex(char[] key) { return unbox!(T)(_objects[key]); } } alias opIndex_T!(int).opIndex opIndex; and it should work now. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 3/03/2006 3:14:03 PM
Mar 02 2006
parent Derek Parnell <derek psych.ward> writes:
On Thu, 2 Mar 2006 21:38:09 -0800, Brad Roberts wrote:

 On Fri, 3 Mar 2006, Derek Parnell wrote:
 
 This works wonderfully for opIndexAssign, but not so much for multiple 
 types of aliases for opIndex.
 
     alias opIndex_T!(int).opIndex opIndex;
     alias opIndex_T!(float).opIndex opIndex;
 

That would because one can't overload the return type. Your code is kinda like doing ... int opIndex(char[] x) ... float opIndex(char[] x) ... and that just ain't going to fly. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 3/03/2006 4:45:56 PM
Mar 02 2006
prev sibling parent Brad Roberts <braddr puremagic.com> writes:
On Fri, 3 Mar 2006, Derek Parnell wrote:

 When I did this sort of thing I had to chnage the template name to be
 different to the member inside the template *and* I had to instantiate the
 member inside the class. The instantiation didn't surprise me but the
 naming conflict one did. Anyhow, replace ...
 
      template opIndex(T)
      {   
          T opIndex(char[] key)
          {   
              return unbox!(T)(_objects[key]);
          }
      }
 
 with ...
 
     template opIndex_T(T)
     {
         T opIndex(char[] key)
         {
             return unbox!(T)(_objects[key]);
         }
     }
     alias opIndex_T!(int).opIndex opIndex;
 
 and it should work now.
 
 -- 
 Derek
 (skype: derek.j.parnell)
 Melbourne, Australia
 "Down with mediocracy!"
 3/03/2006 3:14:03 PM

This works wonderfully for opIndexAssign, but not so much for multiple types of aliases for opIndex. alias opIndex_T!(int).opIndex opIndex; alias opIndex_T!(float).opIndex opIndex; test.d(54): function alias opIndex called with argument types: (char[3]) matches both: test.ValueContainer.opIndex_T!(int).opIndex(char[]) and: test.ValueContainer.opIndex_T!(float).opIndex(char[]) test.d(55): function alias opIndex called with argument types: (char[3]) matches both: test.ValueContainer.opIndex_T!(int).opIndex(char[]) and: test.ValueContainer.opIndex_T!(float).opIndex(char[]) test.d(56): function expected before (), not 0 of type int So close... Brad
Mar 02 2006