www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - __traits(getDelegate, ...)

reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
I wanted to put forth again a proposal I had for getting a delegate to an  
overloaded function.  Only because I think it's relevant to the latest  
property debate.

When getting the address of a delegate, it's as simple as:

struct S
{
    void foo(int x) {}
}

S s;
auto dg = &s.foo; // delegate obtained

However, if foo is overloaded, this becomes more complex:

struct S
{
    void foo(int x) {}
    void foo(string s) {}
}

S s;
auto dg = &s.foo; // which one?  Compiler chooses!

Turns out, it's somewhat possible to specify, but it can be  
painful/uintuitive:

auto dg = cast(void delegate(string))&s.foo; // oops, what if I use the  
wrong delegate signature, or S.foo is changed later!

How about getting a delegate using __traits?

auto dg = __traits(getDelegate, s.foo, string);

Maybe not quite as pretty as &s.foo, but at least allows you to form a  
good expression without a cast.

Now, why is this relevant now?  It could be useful for properties as  
well.  It could allow obtaining a delegate to a property (arguably a very  
rare occurrence), where the current property proposal uses a funky  
parentheses technique for it (which seems unintuitive for a C expression  
to be changed by adding parentheses).

Full proposal:

__traits(getDelegate, symbol, arg1, arg2, ..., argN)

The args are optional, only needed if overloads exist.  If overloads  
exist, args MUST be specified (to protect against future changes).  In the  
special case where one of the overloads has no arguments, void must be  
specified for that overload.

Rules/syntax subject to debate.

Destroy!

-Steve
Feb 03 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/4/13 12:14 AM, Steven Schveighoffer wrote:
 I wanted to put forth again a proposal I had for getting a delegate to
 an overloaded function. Only because I think it's relevant to the latest
 property debate.

 When getting the address of a delegate, it's as simple as:

 struct S
 {
 void foo(int x) {}
 }

 S s;
 auto dg = &s.foo; // delegate obtained

 However, if foo is overloaded, this becomes more complex:

 struct S
 {
 void foo(int x) {}
 void foo(string s) {}
 }

 S s;
 auto dg = &s.foo; // which one? Compiler chooses!

 Turns out, it's somewhat possible to specify, but it can be
 painful/uintuitive:

 auto dg = cast(void delegate(string))&s.foo; // oops, what if I use the
 wrong delegate signature, or S.foo is changed later!
void delegate(string) dg = &s.foo; Andrei
Feb 03 2013
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 04 Feb 2013 00:20:22 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 2/4/13 12:14 AM, Steven Schveighoffer wrote:
 Turns out, it's somewhat possible to specify, but it can be
 painful/uintuitive:

 auto dg = cast(void delegate(string))&s.foo; // oops, what if I use the
 wrong delegate signature, or S.foo is changed later!
void delegate(string) dg = &s.foo;
That seems, ... odd. How does the lhs dictate the rhs expression type? Trying to think of a case where an expression is more handy than assigning to a variable first... Possibly this? Kind of a stretch. void delayedCall(D)(D dg) { // put dg as a delegate onto a message queue to call later... } -Steve
Feb 03 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/4/13 12:32 AM, Steven Schveighoffer wrote:
 On Mon, 04 Feb 2013 00:20:22 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 2/4/13 12:14 AM, Steven Schveighoffer wrote:
 Turns out, it's somewhat possible to specify, but it can be
 painful/uintuitive:

 auto dg = cast(void delegate(string))&s.foo; // oops, what if I use the
 wrong delegate signature, or S.foo is changed later!
void delegate(string) dg = &s.foo;
That seems, ... odd. How does the lhs dictate the rhs expression type? Trying to think of a case where an expression is more handy than assigning to a variable first... Possibly this? Kind of a stretch. void delayedCall(D)(D dg) { // put dg as a delegate onto a message queue to call later... } -Steve
This is well-trodden ground. The rule has been in C++ forever and has worked well. It's time-proven, and there is little reason to mess with what works. Andrei
Feb 03 2013
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 04 Feb 2013 00:39:04 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 This is well-trodden ground. The rule has been in C++ forever and has  
 worked well. It's time-proven, and there is little reason to mess with  
 what works.
Fair enough. Withdrawn. -Steve
Feb 03 2013
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Monday, 4 February 2013 at 05:39:04 UTC, Andrei Alexandrescu 
wrote:
 This is well-trodden ground. The rule has been in C++ forever 
 and has worked well. It's time-proven, and there is little 
 reason to mess with what works.
C++ is notoriously confusing, odd, weird, and basically any adjective except straightforward, simple and clear.
Feb 03 2013
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-02-04 06:20, Andrei Alexandrescu wrote:

 void delegate(string) dg = &s.foo;
I know that this expression works. But since this works, why can't we overload on the return value. This seems to be do exactly this. The arguments I heard against overloading on the return value is due the LHS of an expression shouldn't affect the RHS. -- /Jacob Carlborg
Feb 04 2013
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/4/13 3:01 AM, Jacob Carlborg wrote:
 On 2013-02-04 06:20, Andrei Alexandrescu wrote:

 void delegate(string) dg = &s.foo;
I know that this expression works. But since this works, why can't we overload on the return value. This seems to be do exactly this. The arguments I heard against overloading on the return value is due the LHS of an expression shouldn't affect the RHS.
I think overloading on the return value of functions can be made to work. I understand how it makes it more difficult on the side of the compiler writer, but it's not impossible. The main argument against it is that it adds yet another layer of difficulty in name resolution for function calls. Andrei
Feb 04 2013