Mixins, alias parameters, and alias template instantiations
Chris Nicholson-Sauls
ibisbasenji at gmail.com
Mon Sep 18 13:57:59 PDT 2006
Reiner Pope wrote:
> I find it rather frustrating that D seems like it should be able to do
> what I want, but somehow it can't.
>
> One common form of boilerplate code that mixins seem like a good
> candidate for is properties -- especially getters. So, I tried to write
> mixins that made this less work (like Ruby's attr_reader). Basically, I
> was hoping that we could mix in and rename a function, but the renaming
> bit doesn't seem to work. Here's what I tried:
>
> template getter(alias val)
> {
> typeof(val) getter() { return val; }
> }
>
> class Foo
> {
> int a;
> mixin getter!(a) bar;
> alias getter!(a) foo; // Fails with error message 1 below.
>
> unittest
> {
> Foo f = new Foo();
> writefln(f.getter()); // This works, but it isn't what I want
> writefln(f.foo()); // I want the property to appear like this
> writefln(f.bar()); // Or this, but this gives errors 2 and 3.
> // And of course, f.foo() doesn't exist since it couldn't be
> alias'ed in.
> }
> }
>
> Error messages:
> 1. template instance cannot use local 'a' as template parameter
> 2. undefined identifier (f dotexp mixin getter!(a);
> ).opCall
> 3. function expected before (), not (f dotexp mixin getter!(a);
> ).opCall of type void
>
> I can understand why the alias instantiation fails, and I understand
> that the following would achieve what I want:
>
> mixin getter!(a) _g;
> alias _g.getter bar;
>
> but that then means two lines of code, and namespace pollution, for what
> should really be a trivial task.
>
> What I would like is, just like for normal templates, a single item
> would be an Implicit Template Property, and could thus be renamed. This
> would just be a special syntactical shorthand for single elements, such
> as the case I described here.
>
> I hope you like it.
>
> Cheers,
>
> Reiner
The following will accomplish what you want, even if it is slightly counter-intuitive.
# import std .stdio ;
#
# template MGettor (alias Fld) {
# typeof(Fld) opCall () {
# return Fld;
# }
# }
#
# class Foo {
# int a = 1 ,
# b = 2 ;
#
# mixin MGettor!(a) getA ;
# mixin MGettor!(b) getB ;
# }
#
# void main () {
# auto foo = new Foo;
#
# writefln(foo.getA());
# writefln(foo.getB());
# }
Caveat: Forget the parentheses when calling the gettor, and you get an ICE. Eek. (Breaks
properties syntax, therefore.)
-- Chris Nicholson-Sauls
More information about the Digitalmars-d
mailing list