digitalmars.D - Template namespaces - Obsolete?
- Janice Caron (27/27) Sep 19 2007 Now that we can do:
- Bill Baxter (22/38) Sep 19 2007 Mixins as you mention.
- Kirk McDonald (45/79) Sep 19 2007 The template namespace notation is still very useful. Pyd uses it
- Michel Fortin (21/28) Sep 19 2007 I haven't seen it yet, but templates are very powerful when combined
- BCS (21/54) Sep 19 2007 That reminds me of another uses for the full form
- BCS (14/48) Sep 19 2007 one other use of it is where a collection of things needs to be passed
- Walter Bright (5/23) Sep 19 2007 Yes. It makes sense to logically group related templates together,
Now that we can do: class A(T); struct A(T); union A(T); T func(T)(T x); static int func(int n); ... etc. Is there any need, any more, for the old fashioned template t(T) { int f(); int g(); } and having to refer to t!(T).f() and t!(T).g() ? I almost think it would suffice to complete the new notation with obvious extensions like typedef(T) something t; /* == template t(T) { typedef something t; } */ alias(T) something t; /* == template t(T) { typedef something t; } */ enum(T) t : T {...}; /* == template t(T) { enum t : T {...}; } */ int a(int N)[N]; /* == template a(int N) { int a[N]; } */ (Not too sure about the usefulness of that last one, but I include if for completion). and then deprecate the old namespace notation. The namespace notation is very useful for defining mixins though, and perhaps that has now become its primary purpose. If that functionality is ever replaced by "macro", what then?
Sep 19 2007
Janice Caron wrote:Now that we can do: class A(T); struct A(T); union A(T); T func(T)(T x); static int func(int n); ... etc. Is there any need, any more, for the old fashioned template t(T) { int f(); int g(); }Mixins as you mention. That also includes mixins as a work around for lack of inner namespaces. I doubt macros will ever be able to create new namespaces. Also it's just handy for cases where you have a few functions that all share the same collection of derived types etc. template AutoRepair(CarType) { alias CarType.wheel_type Wheel; alias CarType.body_type Body; alias CarType.engine_type Engine; alias Engine.fuel_type Fuel; alias CarType.transmission_type Transmision; alias CarType.manufacturer manufacturer; // returns the new Engine Engine fix_engine(CarType car, Engine replacement_part) { ... } // returns the new body Body repair_body(CarType car, Body replacement_part) { ... } /// etc... } --bb
Sep 19 2007
Janice Caron wrote:Now that we can do: class A(T); struct A(T); union A(T); T func(T)(T x); static int func(int n); ... etc. Is there any need, any more, for the old fashioned template t(T) { int f(); int g(); } and having to refer to t!(T).f() and t!(T).g() ? I almost think it would suffice to complete the new notation with obvious extensions like typedef(T) something t; /* == template t(T) { typedef something t; } */ alias(T) something t; /* == template t(T) { typedef something t; } */ enum(T) t : T {...}; /* == template t(T) { enum t : T {...}; } */ int a(int N)[N]; /* == template a(int N) { int a[N]; } */ (Not too sure about the usefulness of that last one, but I include if for completion). and then deprecate the old namespace notation. The namespace notation is very useful for defining mixins though, and perhaps that has now become its primary purpose. If that functionality is ever replaced by "macro", what then?The template namespace notation is still very useful. Pyd uses it extensively. Some examples are: // A templated AA. template wrapped_gc_references(T) { PyObject*[T] wrapped_gc_references; } // A template for deriving the signatures of a property, given an // alias to it: template property_parts(alias p) { // This may be either the getter or the setter alias typeof(&p) p_t; alias ParameterTypeTuple!(p_t) Info; // This means it's the getter static if (Info.length == 0) { alias p_t getter_type; // The setter may return void, or it may return the newly // set attribute. alias typeof(p(ReturnType!(p_t).init)) function(ReturnType!(p_t)) setter_type; // This means it's the setter } else { alias p_t setter_type; alias Info[0] function() getter_type; } } It also uses this idiom extensively: An extern(C) function inside a template. template wrapped_repr(T, alias fn) { extern(C) PyObject* repr(PyObject* self) { return exception_catcher(delegate PyObject*() { return method_wrap!(T, fn, char[] function()).func(self, null); }); } } Things can get weird if you declare an extern(C) function template. (Or at least they used to; I haven't tried it in ages. This idiom also dates back to before the short-hand syntax for function templates existed, although this particular code is fairly new.) -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Sep 19 2007
On 2007-09-19 15:23:36 -0400, "Janice Caron" <caron800 googlemail.com> said:Is there any need, any more, for the old fashioned template t(T) { int f(); int g(); }I haven't seen it yet, but templates are very powerful when combined with static if. You can only do that the "old fashioned" way. This code is from the D/Objective-C bridge I released yesterday: /** * Number of arguments in method name. This simply count the number of * colon character within the string. */ template methodArgumentCount(char[] name) { static if (name.length == 0) { const uint methodArgumentCount = 0; } else static if (name[0] == ':') { const uint methodArgumentCount = 1 + methodArgumentCount!(name[1..$]); } else { const uint methodArgumentCount = methodArgumentCount!(name[1..$]); } } -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 19 2007
Michel Fortin wrote:On 2007-09-19 15:23:36 -0400, "Janice Caron" <caron800 googlemail.com> said:That reminds me of another uses for the full form template Foo(bool b) { static if(b) alias T!(int, float, char) args; else alias T!(short byte) args; void Bar(args val){} } Iv never actually had code where I needed that, but I came close. What I ended up with was this: enum Ver { zero = 0, one = 1, two = 2 } T!(byte, short, int)[t] Foo(Ver t)(T!(int, short, byte)[0..t] args){} I was just lucky enough that the order of the args was the same for all cases, just some of them omitted the later ones. (That was some nasty code!)Is there any need, any more, for the old fashioned template t(T) { int f(); int g(); }I haven't seen it yet, but templates are very powerful when combined with static if. You can only do that the "old fashioned" way. This code is from the D/Objective-C bridge I released yesterday: /** * Number of arguments in method name. This simply count the number of * colon character within the string. */ template methodArgumentCount(char[] name) { static if (name.length == 0) { const uint methodArgumentCount = 0; } else static if (name[0] == ':') { const uint methodArgumentCount = 1 + methodArgumentCount!(name[1..$]); } else { const uint methodArgumentCount = methodArgumentCount!(name[1..$]); } }
Sep 19 2007
Janice Caron wrote:Now that we can do: class A(T); struct A(T); union A(T); T func(T)(T x); static int func(int n); ... etc. Is there any need, any more, for the old fashioned template t(T) { int f(); int g(); } and having to refer to t!(T).f() and t!(T).g() ? I almost think it would suffice to complete the new notation with obvious extensions like typedef(T) something t; /* == template t(T) { typedef something t; } */ alias(T) something t; /* == template t(T) { typedef something t; } */ enum(T) t : T {...}; /* == template t(T) { enum t : T {...}; } */ int a(int N)[N]; /* == template a(int N) { int a[N]; } */ (Not too sure about the usefulness of that last one, but I include if for completion). and then deprecate the old namespace notation. The namespace notation is very useful for defining mixins though, and perhaps that has now become its primary purpose. If that functionality is ever replaced by "macro", what then?one other use of it is where a collection of things needs to be passed around template Foo(char[] str) { const char[] post = str[IndexOfFirst(':').In(str)..$]; const char[] pre = str[0..pre.length]; } alias Foo!("hello:world") bar; bar.pre; bar.post; dparse uses this to build parse trees at compile time*. * actually it puts them inside a struct but that is to work around a bug in DMD and causes a host of other issues.
Sep 19 2007
Janice Caron wrote:Now that we can do: class A(T); struct A(T); union A(T); T func(T)(T x); static int func(int n); ... etc. Is there any need, any more, for the old fashioned template t(T) { int f(); int g(); } and having to refer to t!(T).f() and t!(T).g() ?Yes. It makes sense to logically group related templates together, instead of the C++ ad-hoc approach where a file has a mess of arbitrary looking templates, and no organizational cues as to which ones belong together.
Sep 19 2007