www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Partial classes & forward declarations

reply Manu <turkeyman gmail.com> writes:
--20cf300e4de740d17404be1b23f9
Content-Type: text/plain; charset=UTF-8

So I've been running into cases repeatedly all week where I really need one
or the other, or in some cases, both of these so solve some meta problems,
relating to rich bindings to a C++ code base.

I'm currently rolling with quite a few workarounds for various things, but
I've finally reached an impass.
Here's my problem, and maybe people can suggest some nice workaround to
this one...

I have a class, and it contains various method declarations. These methods
are to be implemented via mixins which generate stubs binding it to some
complex C++ call-through mechanism.
My approach was to allow the user to forward declare the methods, which
will tell the compiler all the information about the function call, and
then later on, a mixin would scan the class for such methods, and produce
the actual function stubs accordingly.
This doesn't work, because the compiler gives me a message that it is an
ambiguous call, even though it is actually the exact same function declared
twice (once as a forward declaration).

So apparently forward declarations aren't supported, even though they
appeared to be... then I found this: "The program is looked at as a whole,
and so not only is it not necessary to code forward declarations, it is not
even allowed! "
Well, in this case, a forward declaration is necessary, since it
effectively provides the compiler with the signature that it can use to
generate the function, in a way that looks exactly like a function
definition to anyone who is reading the code.
Having failed that, I have a workaround where I name the function with a
silly prefix, and make it private... but this makes no sense to someone
reading the source for the binding class (they see a weird list of private
mangled functions). So I'm not entirely happy with the solution, but it
does technically work for the moment.

There is a secondary problem with my workaround though... I can't figure
any way to *alias* a function argument, I can only get a typetuple of the
arguments. Since I don't have _alias_es of the function args, I have no way
to access their 'identifier'(/name), and that leads to a problem where I'm
generating the public stub function, and I have nothing to name the args
other than a0, a1, a2, etc...
That is complete rubbish, and unusable to an end user by my measure;
intellisense is useless if the pop-up argument list says a0,a1,a2. >_<

There's a third crudeness to my problem, and that is, to generate the
bindings, I need to put a mixin in every class. I already have a
'RegisterModule' mixin at the end of the file, which binds all the
'loose'/static methods.
What would be really handy in this case, is to be able to use partial
classes as in C# and C++0x to add the extra bits to the previously defined
classes all within the one RegisterModule at the end.
I think partial classes will become considerably more useful too when we
have attributes, and some may classes need to have some extra data members
added to support their given attributes.

So let's ignore partial classes for the moment, I'm happy enough with the
meta spam for the time being. What kinds of tricks can I use to generate
the stub functions I want, while preserving the argument names, and
sensible declaration/readibility of the module. How else could the
functions be declared, short of a string literal, is there any way I can
pull out the names of args currently?

I think there's definitely room for a trait to refer to the _instance_ of a
function arg in the same way as 'getMember', thus allowing it to be
enumerated+supplied to templates as alias parameters.

--20cf300e4de740d17404be1b23f9
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

So I&#39;ve been running into cases repeatedly all week where I really need=
 one or the other, or in some cases, both of these so solve some meta probl=
ems, relating=C2=A0to rich bindings to a C++ code base.<div><br></div><div>=
I&#39;m currently rolling with quite a few workarounds for various things, =
but I&#39;ve finally reached an impass.</div>
<div>Here&#39;s my problem, and maybe people can suggest some nice workarou=
nd to this one...</div><div><br></div><div>I have a class, and it contains =
various method declarations. These methods are to be implemented via mixins=
 which generate stubs binding it to some complex C++ call-through mechanism=
.</div>
<div>My approach was to allow the user to forward declare the methods, whic=
h will tell the compiler all the information about the function call, and t=
hen later on, a mixin would scan the class for such methods, and produce th=
e actual function stubs accordingly.</div>
<div>This doesn&#39;t work, because the compiler gives me a message that it=
 is an ambiguous call, even though it is actually the exact same function d=
eclared twice (once as a forward declaration).</div><div><br>So apparently =
forward declarations aren&#39;t supported, even though they appeared to be.=
.. then I found this:=C2=A0<span style=3D"background-color:rgb(246,246,246)=
;font-family:Consolas,monospace;font-size:14px;white-space:pre-wrap">&quot;=
The program is looked at as a whole, and so not only is it not </span><span=
 style=3D"background-color:rgb(246,246,246);font-family:Consolas,monospace;=
font-size:14px;white-space:pre-wrap">necessary to code forward declarations=
, it is not even allowed! &quot;</span></div>
<div>Well, in this case, a forward declaration is necessary, since it effec=
tively provides the compiler with the signature that it can use to generate=
 the function, in a way that looks exactly like a function definition to an=
yone who is reading the code.</div>
<div>Having failed that, I have a workaround where I name the function with=
 a silly prefix, and make it private... but this makes no sense to someone =
reading the source for the binding class (they see a weird list of private =
mangled functions). So I&#39;m not entirely happy with the solution, but it=
 does technically work for the moment.</div>
<div><br></div><div>There is a secondary problem with my workaround though.=
.. I can&#39;t figure any way to *alias* a function argument, I can only ge=
t a typetuple of the arguments. Since I don&#39;t have _alias_es of the fun=
ction args, I have no way to access their &#39;identifier&#39;(/name), and =
that leads to a problem where I&#39;m generating the public stub function, =
and I have nothing to name the args other than a0, a1, a2, etc...</div>
<div>That is complete rubbish, and unusable to an end user by my measure; i=
ntellisense is useless if the pop-up argument list says a0,a1,a2. &gt;_&lt;=
</div><div><br></div><div>There&#39;s a third crudeness to my problem, and =
that is, to generate the bindings, I need to put a mixin in every class. I =
already have a &#39;RegisterModule&#39; mixin at the end of the file, which=
 binds all the &#39;loose&#39;/static methods.</div>
<div>What would be really handy in this case, is to be able to use partial =
classes as in C# and C++0x to add the extra bits to the previously defined =
classes all within the one RegisterModule at the end.</div><div>I think par=
tial classes will become considerably more useful too when we have attribut=
es, and some may classes need to have some extra data members added to supp=
ort their given attributes.</div>
<div><br></div><div>So let&#39;s ignore partial classes for the moment, I&#=
39;m happy enough with the meta spam for the time being. What kinds of tric=
ks can I use to generate the stub functions I want, while preserving the ar=
gument names, and sensible declaration/readibility of the module. How else =
could the functions be declared, short of a string literal, is there any wa=
y I can pull out the names of args currently?</div>
<div><br></div><div>I think there&#39;s definitely room for a trait to refe=
r to the _instance_ of a function arg in the same way as &#39;getMember&#39=
;, thus allowing it to be enumerated+supplied to templates as alias paramet=
ers.</div>

--20cf300e4de740d17404be1b23f9--
Apr 20 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-20 14:07, Manu wrote:

 There is a secondary problem with my workaround though... I can't figure
 any way to *alias* a function argument, I can only get a typetuple of
 the arguments. Since I don't have _alias_es of the function args, I have
 no way to access their 'identifier'(/name), and that leads to a problem
 where I'm generating the public stub function, and I have nothing to
 name the args other than a0, a1, a2, etc...
 That is complete rubbish, and unusable to an end user by my measure;
 intellisense is useless if the pop-up argument list says a0,a1,a2. >_<

Don't know if it helps but you can get the name of the arguments of a function: https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d#L29 I don't think that function handles delegate/function parameters. -- /Jacob Carlborg
Apr 20 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-20 16:47, Manu wrote:

 Bummer. I still think there's room for a formal trait to do this.
 Complimentary to allMembers and getMember, but for a functions.

The function currently just splits the string on ",". It would be possible to add a more sophisticated algorithm to handle delegate and function pointer parameters. -- /Jacob Carlborg
Apr 21 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 21-04-2012 16:32, Jacob Carlborg wrote:
 On 2012-04-20 16:47, Manu wrote:

 Bummer. I still think there's room for a formal trait to do this.
 Complimentary to allMembers and getMember, but for a functions.

The function currently just splits the string on ",". It would be possible to add a more sophisticated algorithm to handle delegate and function pointer parameters.

It would basically mean having to parse D's full type syntax to be 100% correct, which is not cool. The compiler ought to help out here. -- - Alex
Apr 21 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-04-21 17:45, Alex Rønne Petersen wrote:

 It would basically mean having to parse D's full type syntax to be 100%
 correct, which is not cool. The compiler ought to help out here.

Yet again we need a compiler library. -- /Jacob Carlborg
Apr 21 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-04-20 18:21, Jakob Ovrum wrote:
 On Friday, 20 April 2012 at 14:19:25 UTC, Jacob Carlborg wrote:
 Don't know if it helps but you can get the name of the arguments of a
 function:

 https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d#L29


 I don't think that function handles delegate/function parameters.

This function is too naive, it's incredibly easy to break. void foo(immutable(int) a);

Yeah, I know. This function more or less shows it's possible. -- /Jacob Carlborg
Apr 21 2012
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--e89a8f3bb0cf9f039a04be1d5cb8
Content-Type: text/plain; charset=UTF-8

On 20 April 2012 17:19, Jacob Carlborg <doob me.com> wrote:

 On 2012-04-20 14:07, Manu wrote:

  There is a secondary problem with my workaround though... I can't figure
 any way to *alias* a function argument, I can only get a typetuple of
 the arguments. Since I don't have _alias_es of the function args, I have
 no way to access their 'identifier'(/name), and that leads to a problem
 where I'm generating the public stub function, and I have nothing to
 name the args other than a0, a1, a2, etc...
 That is complete rubbish, and unusable to an end user by my measure;
 intellisense is useless if the pop-up argument list says a0,a1,a2. >_<

Don't know if it helps but you can get the name of the arguments of a function: https://github.com/jacob-**carlborg/orange/blob/master/** orange/util/Reflection.d#L29<https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d#L29>

Amazing, that needs to go in std.traits pronto! :P This should help with my hack in the mean time. I don't think that function handles delegate/function parameters. Bummer. I still think there's room for a formal trait to do this. Complimentary to allMembers and getMember, but for a functions. --e89a8f3bb0cf9f039a04be1d5cb8 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On 20 April 2012 17:19, Jacob Carlborg <span dir= =3D"ltr">&lt;<a href=3D"mailto:doob me.com">doob me.com</a>&gt;</span> wrot= e:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l= eft:1px #ccc solid;padding-left:1ex"> <div class=3D"im">On 2012-04-20 14:07, Manu wrote:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> There is a secondary problem with my workaround though... I can&#39;t figur= e<br> any way to *alias* a function argument, I can only get a typetuple of<br> the arguments. Since I don&#39;t have _alias_es of the function args, I hav= e<br> no way to access their &#39;identifier&#39;(/name), and that leads to a pro= blem<br> where I&#39;m generating the public stub function, and I have nothing to<br=

That is complete rubbish, and unusable to an end user by my measure;<br> intellisense is useless if the pop-up argument list says a0,a1,a2. &gt;_&lt= ;<br> </blockquote> <br></div> Don&#39;t know if it helps but you can get the name of the arguments of a f= unction:<br> <br> <a href=3D"https://github.com/jacob-carlborg/orange/blob/master/orange/util= /Reflection.d#L29" target=3D"_blank">https://github.com/jacob-<u></u>carlbo= rg/orange/blob/master/<u></u>orange/util/Reflection.d#L29</a></blockquote> <div><br></div><div>Amazing, that needs to go in std.traits pronto! :P</div=
<div>This should help with my hack in the mean time.</div><div><br></div><=

border-left:1px #ccc solid;padding-left:1ex"> I don&#39;t think that function handles delegate/function parameters.</bloc= kquote><div><br></div><div>Bummer. I still think there&#39;s room for a for= mal trait to do this. Complimentary to allMembers and getMember, but for a = functions.</div> </div> --e89a8f3bb0cf9f039a04be1d5cb8--
Apr 20 2012
prev sibling next sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Friday, 20 April 2012 at 14:19:25 UTC, Jacob Carlborg wrote:
 Don't know if it helps but you can get the name of the 
 arguments of a function:

 https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d#L29

 I don't think that function handles delegate/function 
 parameters.

This function is too naive, it's incredibly easy to break. void foo(immutable(int) a);
Apr 20 2012
prev sibling next sibling parent "Martin Nowak" <dawg dawgfoto.de> writes:
 I have a class, and it contains various method declarations. These  
 methods
 are to be implemented via mixins which generate stubs binding it to some
 complex C++ call-through mechanism.
 My approach was to allow the user to forward declare the methods, which
 will tell the compiler all the information about the function call, and
 then later on, a mixin would scan the class for such methods, and produce
 the actual function stubs accordingly.

Not sure if I understood you problem correctly, but these are the two idioms I use regularly. //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: module lib; mixin template genFuncAlias(string fname, RT, Args...) { RT __genFunc(Args args) { //... return RT.init; } mixin("alias __genFunc "~fname~";"); } mixin template genFuncName(string fname, RT, Args...) { enum __s = codegen(fname); mixin(__s); } string codegen(string fname) { import std.array, std.format; auto app = appender!string(); formattedWrite(app, q{ RT %1$s(Args args) { //... return RT.init; } }, fname); return app.data; } //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: module client; import lib; class Blah { // not overloadable ?? mixin genFuncAlias!("bar", int, string, double); // mixin genFuncAlias!("bar", int, double, string); mixin genFuncName!("foo", int, string, double); mixin genFuncName!("foo", int, double, string); } void main() { auto b = new Blah(); b.bar("1.0", 1.0) && assert(0); // not overloadable ?? // b.bar(2.0, "2.0") && assert(0); b.foo("1.0", 1.0) && assert(0); b.foo(2.0, "2.0") && assert(0); } //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: dmd -run client lib
Apr 21 2012
prev sibling parent Manu <turkeyman gmail.com> writes:
--00248c70fdc968d0fb04be32d063
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On 21 April 2012 18:45, Alex R=C3=B8nne Petersen <xtzgzorex gmail.com> wrot=
e:

 On 21-04-2012 16:32, Jacob Carlborg wrote:

 On 2012-04-20 16:47, Manu wrote:

  Bummer. I still think there's room for a formal trait to do this.
 Complimentary to allMembers and getMember, but for a functions.

The function currently just splits the string on ",". It would be possible to add a more sophisticated algorithm to handle delegate and function pointer parameters.

correct, which is not cool. The compiler ought to help out here.

Some traits would be nice; allArguments, getArgument. This would allow enumeration of argument lists in the exact same way as struct members. D has gone hard out with its compile time meta capabilites, but there's just a couple of small things missing from the complete introspection set. --00248c70fdc968d0fb04be32d063 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On 21 April 2012 18:45, Alex R=C3=B8nne Petersen= <span dir=3D"ltr">&lt;<a href=3D"mailto:xtzgzorex gmail.com">xtzgzorex gma= il.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"= margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <div class=3D"HOEnZb"><div class=3D"h5">On 21-04-2012 16:32, Jacob Carlborg= wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> On 2012-04-20 16:47, Manu wrote:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Bummer. I still think there&#39;s room for a formal trait to do this.<br> Complimentary to allMembers and getMember, but for a functions.<br> </blockquote> <br> The function currently just splits the string on &quot;,&quot;. It would be= <br> possible to add a more sophisticated algorithm to handle delegate and<br> function pointer parameters.<br> <br> </blockquote> <br></div></div> It would basically mean having to parse D&#39;s full type syntax to be 100%= correct, which is not cool. The compiler ought to help out here.</blockquo= te><div><br></div><div>Some traits would be nice; allArguments, getArgument= .</div> <div>This would allow enumeration of argument lists in the exact same way a= s struct members.</div><div><br></div><div>D has gone hard out with its com= pile time meta capabilites, but there&#39;s just a couple of small things m= issing from the complete introspection set.</div> </div> --00248c70fdc968d0fb04be32d063--
Apr 21 2012