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