More Thoughts [was: "spirit" in 100LOC]

BCS BCS at pathilink.com
Tue Dec 19 10:27:26 PST 2006


After a bit of consideration and puzzling, I think I have figured out 
what is going on with the mixins, templates and specializations. From 
this, I'm not sure if what is happening is a bug or not. However it 
definitely prevents my program from working and blocks off a whole set 
of functionality for D templates.

*What I'm trying to do:*

I'm trying to mixin several function templates into the same scope, all 
with the same name, but differently specialized. This would effectively 
allow for identifier generation from strings.

void Foo(char[] s: "hello")(){}
void Foo(char[] s: "world")(){}

void fn(char[] string)()
{
  Foo!(string)();	// go find a Foo to call
}

The usefulness of this comes in when the string that is used comes from 
template processing. A dumb example of this could convert a string to an 
expression evaluation (why someone would want to do that...)

Eval!("SET this FROM that USING something over there")();
goes to:
Val!("this")=Act!("that")(Val!("something"),Val!("over"),Val!("there"));

*What is Happening That Prevents This:*

Things are getting mixed in for the most part. However it seems 
specializations for a template must all reside in the same "mixin 
scope". Supposedly through the use of named mixins and aliases, 
overloading of functions using more than one mixin can work. However 
this doesn't seem to work when generating specializations. This seems to 
be the same problem as experienced by Bill Baxter, namely that function 
templates aren't functions, but templates with functions in them. This 
causes problems because some things that work for functions don't work 
for templates. Importantly, templates mixed in from different scope 
don't overload.

*What Would Be Needed To Allow This:*

Two things would be needed. Firstly, some means to make a mixed in 
template (a template inside of a template that is used as a mixin) 
overload with other templates at the scope it is mixed into. Without 
this, none of this will be of much use.
	Secondly, A problems involving order-of-instancing shows up with 
templates as it is. If two template specialization refer to each other, 
there is the possibility that one of them will try to instance the other 
before the specialization for the other is created. The result would be 
either a compile error or an attempt to instance the wrong template. On 
the other hand, if I'm not missing something, a compiler would also be 
correct to lazy evaluate specializations, in which case this problem may 
well not occur. Some way to ensure the desired behavior here would be 
needed.
	One solution would be to define an "abstract template" at the outermost 
scope. This template would have no implementation, but would specify 
what symbols are to be generated. Any use of this template would skip 
the argument deduction rules for templates and just assume that an exact 
specialization will exist. If one is not specified, then an error is 
generated later, probably at link time.

Template Mapper(char[] from, char[] to)
{
  template Map(char[] string: from)
  {
   const char[] Map = to;
  }
}

struct Foo
{
  abstract template Map(char[])
  {
   const char[] Map;
  }

  void fn()
  {
   writeln("%s", Map!("hello"));	// maps "hello" to "world"
   writeln("%s", Map!("good"));	// link error
  }

  mixin Mapper!("hello", "world");
}

[1] see mixin.html down at the bottom
[2] digitalmars.D.learn:"Q about template function overloads"
[3] see "Argument Deduction" in template.html



More information about the Digitalmars-d-announce mailing list