www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Template namespaces - Obsolete?

reply "Janice Caron" <caron800 googlemail.com> writes:
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
next sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
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
prev sibling next sibling parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
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
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
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
parent BCS <BCS pathlink.com> writes:
Michel Fortin wrote:
 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..$]); } }

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!)
Sep 19 2007
prev sibling next sibling parent BCS <BCS pathlink.com> writes:
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
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
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