www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Passing a module in a template parameter list to __traits(allMembers,

reply "Ben Gertzfield" <bgertzfield gmail.com> writes:
Hi folks,

In preparation for my upcoming talk at DConf 2013, I'm working on 
a compile-time dependency injection prototype for D.

I'd like part of public interface for this system to take a 
module at compile time, and return a list of the classes in that 
module. Something like:

string GetMembers(T)() {
   auto members = [__traits(allMembers, T)];
   return join(result, ", ");
}

If I pass a module to __traits(allMembers, foo.bar) outside a 
template parameter list, it works great, but as soon as I pass it 
through a template parameter list, I get an odd error:

Error: template instance GetMembers!(std) GetMembers!(std) does 
not match template declaration GetMembers(T)()

Here's the code I'm working on. Any thoughts on whether this is 
possible, and if so, what I'm doing wrong?

http://pastebin.com/BgZ67h8P

Thanks,

Ben
Feb 26 2013
next sibling parent reply "Andrej Mitrovic" <andrej.mitrovich gmail.com> writes:
On Tuesday, 26 February 2013 at 19:03:01 UTC, Ben Gertzfield 
wrote:
 Hi folks,

 In preparation for my upcoming talk at DConf 2013, I'm working 
 on a compile-time dependency injection prototype for D.

 I'd like part of public interface for this system to take a 
 module at compile time, and return a list of the classes in 
 that module. Something like:

 string GetMembers(T)() {
   auto members = [__traits(allMembers, T)];
   return join(result, ", ");
 }

Use an alias: string GetMembers(alias T)() { auto members = [__traits(allMembers, T)]; return join(members, ", "); } void main() { stdout.writefln("Got members: %s", GetMembers!(std.stdio)); } Also make sure you parenthesize the call in GetMembers. For some reason these two are different: GetMembers!std.stdio // actually calls (GetMembers!std).stdio GetMembers!(std.stdio) That could be a bug though.
Feb 26 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-02-26 20:29, Andrej Mitrovic wrote:

 Well it's definitely an edge-case we'll have to be careful about. :)

 I don't know why packages can be passed as an alias. Do we have any
 defined behavior for using packages and traits?

What the original post is doing, getting all its members? -- /Jacob Carlborg
Feb 26 2013
prev sibling next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/26/2013 11:03 AM, Ben Gertzfield wrote:
 Hi folks,

 In preparation for my upcoming talk at DConf 2013, I'm working on a
 compile-time dependency injection prototype for D.

 I'd like part of public interface for this system to take a module at
 compile time, and return a list of the classes in that module. Something
 like:

 string GetMembers(T)() {
 auto members = [__traits(allMembers, T)];
 return join(result, ", ");
 }

 If I pass a module to __traits(allMembers, foo.bar) outside a template
 parameter list, it works great, but as soon as I pass it through a
 template parameter list, I get an odd error:

 Error: template instance GetMembers!(std) GetMembers!(std) does not
 match template declaration GetMembers(T)()

 Here's the code I'm working on. Any thoughts on whether this is
 possible, and if so, what I'm doing wrong?

 http://pastebin.com/BgZ67h8P

 Thanks,

 Ben

Hi Ben, I am in the same boat and I am about to post questions here about code problems. :) Your first code works with three modifications: 1) std.stdio is not a type, so the template parameter list cannot be (T). I used 'alias'. 2) For syntax reasons, you must parenthesize (std.stdio) when passing as a template parameter 3) (You couldn't get to this yet.) A typo: result -> members import std.array; import std.stdio; import std.traits; string GetMembers(alias T)() { auto members = [__traits(allMembers, T)]; return join(members, ", "); } void main() { stdout.writefln("Got members: %s", GetMembers!(std.stdio)); } Ali
Feb 26 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Feb 26, 2013 at 08:07:42PM +0100, Andrej Mitrovic wrote:
[...]
 Also make sure you parenthesize the call in GetMembers. For some
 reason these two are different:
 
 GetMembers!std.stdio  // actually calls (GetMembers!std).stdio
 GetMembers!(std.stdio)
 
 That could be a bug though.

I think it's a problem with the precedence of the binary ! operator. It has higher precedence than '.', so GetMembers!std.stdio gets parsed as (GetMembers!std).stdio. Anyway, I've learned that if the argument after '!' is more than a single token, you should just parenthesize the whole thing, to be on the safe side. T -- BREAKFAST.COM halted...Cereal Port Not Responding. -- YHL
Feb 26 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/26/13, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:
 I think it's a problem with the precedence of the binary ! operator.

Well it's definitely an edge-case we'll have to be careful about. :) I don't know why packages can be passed as an alias. Do we have any defined behavior for using packages and traits?
Feb 26 2013
prev sibling next sibling parent "Ben Gertzfield" <bgertzfield gmail.com> writes:
On Tuesday, 26 February 2013 at 19:07:43 UTC, Andrej Mitrovic 
wrote:

 Use an alias:

 string GetMembers(alias T)() {

Excellent. An alias parameter is just what I was looking for. Thanks, everyone! Ben
Feb 26 2013
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
 Use an alias:

 string GetMembers(alias T)() {

Excellent. An alias parameter is just what I was looking for. Thanks, everyone!

Ben, I present some ideas on this problem in a template tutorial you can find he= re: https://github.com/PhilippeSigaud/D-templates-tutorial In the pdf, it's section 4.3.4 and 4.3.7, in the markdown file, the related sections are https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/D-templa= tes-tutorial.md#allmembers and https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/D-templa= tes-tutorial.md#getting-all-members-even-overloaded-ones And to answer H.S. Teoh's question, from the text: "What=E2=80=99s the point of inspecting a module? Well, first that was just for fun and to see if I could duplicate a module or create a struct with an equivalent members list (all forwarding to the module=E2=80=99s own members). But the real deal for me w= as when using string mixins to generate some type. If the user uses the mixin in its own module, it could create conflicts with already-existing names. So I searched for a way for a mixin template to inspect the module it=E2=80=99s currently being instantiated in. Then, I wanted to write a template that, given a class name, would give me the entire hierarchy it=E2=80=99s i= n (as the local module scope would see it, that was enough for me). Then, while testing std.traits.ParameterTypeTuple, I saw that it gives the parameter typetuple of one function, even when it=E2=80=99s overloaded. So inspecting a module is also a way to get the full list of functions with a particular name and getting the parameter typetuple for each of them."
Feb 26 2013