Thread overview
Referencing an overloaded function
Mar 24, 2012
John
Mar 24, 2012
Philippe Sigaud
Mar 24, 2012
John
Mar 24, 2012
Mantis
Mar 24, 2012
Artur Skawina
Mar 24, 2012
Artur Skawina
Mar 24, 2012
Philippe Sigaud
Mar 24, 2012
Timon Gehr
Mar 25, 2012
Artur Skawina
Mar 25, 2012
Timon Gehr
March 24, 2012
Is there any way to refer to a specific function overload?

For example:

import std.stdio;
import std.traits;

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

void main() {
    writeln(foo.mangleof);
    writeln(ParameterTypeTuple!(foo).stringof);
}

Both of these statements always refer to the first matching function.  If I change the order of declarations for foo, the results change.

Is there a way to reference the second overload in this example?

I can use a function pointer with ParameterTypeTuple to get the correct result, but something like mangleof won't work, since that will return the mangle of the local function pointer instead of the original function.
March 24, 2012
On Sat, Mar 24, 2012 at 13:13, John <nospam@unavailable.com> wrote:
> Is there any way to refer to a specific function overload?

You can use __traits(getOverloads, aggregate, "member") to get all overloads of member aggregate.member. Where an aggregate is a class, a struct or a module.

module pack.mod; // needs to be XXX.YYY for __traits to work

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

template Alias(A...) { alias A Alias;}

void main()
{
    // The Alias!( ) trick is needed to work around a limitation in
alias X Y grammar
    // __traits() is not accepted in an alias: alias
__traits(getOverloads, X, "Y") OV_XY; does not work
    alias Alias!(__traits(getOverloads, pack.mod, "foo")) OV;

    // OV is a tuple holding all the different foo's

    foreach(i, ov; OV)
        writefln("overload #%s: %s", i, typeof(ov).stringof);

    alias OV[1] intFoo; // void foo(int x) {}

    intFoo(1); // calls void foo(int x) {}
}
March 24, 2012
24.03.2012 14:13, John написал:
> Is there any way to refer to a specific function overload?
>
> For example:
>
> import std.stdio;
> import std.traits;
>
> void foo() {}
> void foo(int x) {}
>
> void main() {
>     writeln(foo.mangleof);
>     writeln(ParameterTypeTuple!(foo).stringof);
> }
>
> Both of these statements always refer to the first matching function.  If I change the order of declarations for foo, the results change.
>
> Is there a way to reference the second overload in this example?
>
> I can use a function pointer with ParameterTypeTuple to get the correct result, but something like mangleof won't work, since that will return the mangle of the local function pointer instead of the original function.
>

import std.stdio;
import std.traits;

void foo() { writeln( "void" ); }
void foo( int x ) { writeln( x ); }

template getOverload( alias func, A... ) {
    void function(A) getOverload = &func;
}

void main() {
    writeln( getOverload!(foo, int).mangleof );
    writeln( ParameterTypeTuple!(getOverload!(foo, int)).stringof );
    getOverload!(foo, int)(42);
    getOverload!(foo)();
}

Will not hold for return types other than void, there may be some generic workaround (of course, you can pass return type as tempate parameter).
March 24, 2012
On Saturday, 24 March 2012 at 13:59:30 UTC, Philippe Sigaud wrote:
> module pack.mod; // needs to be XXX.YYY for __traits to work
>
> void foo() {}
> void foo(int x) {}
>
> template Alias(A...) { alias A Alias;}
>
> void main()
> {
>     // The Alias!( ) trick is needed to work around a limitation in
> alias X Y grammar
>     // __traits() is not accepted in an alias: alias
> __traits(getOverloads, X, "Y") OV_XY; does not work
>     alias Alias!(__traits(getOverloads, pack.mod, "foo")) OV;
>
>     // OV is a tuple holding all the different foo's
>
>     foreach(i, ov; OV)
>         writefln("overload #%s: %s", i, typeof(ov).stringof);
>
>     alias OV[1] intFoo; // void foo(int x) {}
>
>     intFoo(1); // calls void foo(int x) {}
> }

That's exactly what I was looking for.  Thanks.

March 24, 2012
On 03/24/12 15:39, Mantis wrote:
> 24.03.2012 14:13, John написал:
>> Is there any way to refer to a specific function overload?
>>
>> For example:
>>
>> import std.stdio;
>> import std.traits;
>>
>> void foo() {}
>> void foo(int x) {}
>>
>> void main() {
>>     writeln(foo.mangleof);
>>     writeln(ParameterTypeTuple!(foo).stringof);
>> }
>>
>> Both of these statements always refer to the first matching function.  If I change the order of declarations for foo, the results change.
>>
>> Is there a way to reference the second overload in this example?
>>
>> I can use a function pointer with ParameterTypeTuple to get the correct result, but something like mangleof won't work, since that will return the mangle of the local function pointer instead of the original function.
>>
> 
> import std.stdio;
> import std.traits;
> 
> void foo() { writeln( "void" ); }
> void foo( int x ) { writeln( x ); }
> 
> template getOverload( alias func, A... ) {
>     void function(A) getOverload = &func;
> }
> 
> void main() {
>     writeln( getOverload!(foo, int).mangleof );
>     writeln( ParameterTypeTuple!(getOverload!(foo, int)).stringof );
>     getOverload!(foo, int)(42);
>     getOverload!(foo)();
> }
> 
> Will not hold for return types other than void, there may be some generic workaround (of course, you can pass return type as tempate parameter).

Something like

> auto getOverload(alias func, A...)(A a) {
>     typeof(foo(a)) function(A) getOverload = &func;
> }

would work.

The problem with that solution is however that .mangleof will return the wrong name.

This:

>     foreach (f; __traits(getOverloads, __traits(parent, main), "foo")) {
>        static if (is(ParameterTypeTuple!f==TypeTuple!(int))) {
>           writeln(f.mangleof);
>           writeln(ParameterTypeTuple!(f).stringof);
>           //writeln(typeof(f).stringof);
>           //f(42);
>           //etc
>        }
>     }

will do the right thing when you need the original name of foo(int).

artur
March 24, 2012
On 03/24/12 18:07, Artur Skawina wrote:
> On 03/24/12 15:39, Mantis wrote:
>> Will not hold for return types other than void, there may be some generic workaround (of course, you can pass return type as tempate parameter).
> 
> Something like
> 
>> auto getOverload(alias func, A...)(A a) {
>>     typeof(foo(a)) function(A) getOverload = &func;
>> }
> 
> would work.
> 
> The problem with that solution is however that .mangleof will return the wrong name.

Of course that should have been something more like:

> template tr(A...) { extern A tr; }
> template getOverload(alias func, A...) {
>     typeof(foo(tr!A)) function(A) getOverload = &func;
> }

and I should actually test the code before posting, even when the compiler tries to make things difficult (Error: functions cannot return a tuple). ;) While this version works now, it's still prevents getting the correct mangled function name - the getOverloads loop approach gets that right.

artur
March 24, 2012
On Sat, Mar 24, 2012 at 18:07, Artur Skawina <art.08.09@gmail.com> wrote:

>>     foreach (f; __traits(getOverloads, __traits(parent, main), "foo")) {

Hey, this
^^^^^^^^^^^^^^^^^^^^^^
it's a way to get the current module, right? Nice trick, I didn't think of this.

Its limitation is it won't work outside the 'main() {}' module.
March 24, 2012
On 03/24/2012 09:07 PM, Philippe Sigaud wrote:
> On Sat, Mar 24, 2012 at 18:07, Artur Skawina<art.08.09@gmail.com>  wrote:
>
>>>      foreach (f; __traits(getOverloads, __traits(parent, main), "foo")) {
>
> Hey, this
> ^^^^^^^^^^^^^^^^^^^^^^
> it's a way to get the current module, right? Nice trick, I didn't think of this.
>
> Its limitation is it won't work outside the 'main() {}' module.


You can get the parent of an alias. The following template finds all overloads of a given symbol:

template ID(T...){alias    T ID;}
template getOverloads(alias f){
    enum fname = f.stringof[0..f.stringof.indexOf("(")];
    alias ID!(__traits(getOverloads, __traits(parent, f), fname)) getOverloads;
}

I think this should go into std.traits, as soon as it works. (DMD is buggy when it comes to taking the .stringof of a function. It misinterprets it as a property function call in some cases but not in others. Messy.)
March 25, 2012
On 03/24/12 23:10, Timon Gehr wrote:
> On 03/24/2012 09:07 PM, Philippe Sigaud wrote:
>> On Sat, Mar 24, 2012 at 18:07, Artur Skawina<art.08.09@gmail.com>  wrote:
>>
>>>>      foreach (f; __traits(getOverloads, __traits(parent, main), "foo")) {
>>
>> Hey, this
>> ^^^^^^^^^^^^^^^^^^^^^^
>> it's a way to get the current module, right? Nice trick, I didn't think of this.
>>
>> Its limitation is it won't work outside the 'main() {}' module.
> 
> 
> You can get the parent of an alias. The following template finds all overloads of a given symbol:
> 
> template ID(T...){alias    T ID;}
> template getOverloads(alias f){
>     enum fname = f.stringof[0..f.stringof.indexOf("(")];
>     alias ID!(__traits(getOverloads, __traits(parent, f), fname)) getOverloads;
> }
> 
> I think this should go into std.traits, as soon as it works. (DMD is buggy when it comes to taking the .stringof of a function. It misinterprets it as a property function call in some cases but not in others. Messy.)

Yeah, your version does not work with my old GDC either (stringof returns really weird things here...);  this one works:

template ID(T...) { alias T ID; }
template getOverloads(alias F) {
   alias ID!(__traits(getOverloads, __traits(parent, F), __traits(identifier, F))) getOverloads;
}

and looks obvious enough; it would be nice to get rid of that extra ID step, though.

artur
March 25, 2012
On 03/25/2012 12:34 AM, Artur Skawina wrote:
> On 03/24/12 23:10, Timon Gehr wrote:
>> On 03/24/2012 09:07 PM, Philippe Sigaud wrote:
>>> On Sat, Mar 24, 2012 at 18:07, Artur Skawina<art.08.09@gmail.com>   wrote:
>>>
>>>>>       foreach (f; __traits(getOverloads, __traits(parent, main), "foo")) {
>>>
>>> Hey, this
>>> ^^^^^^^^^^^^^^^^^^^^^^
>>> it's a way to get the current module, right? Nice trick, I didn't think of this.
>>>
>>> Its limitation is it won't work outside the 'main() {}' module.
>>
>>
>> You can get the parent of an alias. The following template finds all overloads of a given symbol:
>>
>> template ID(T...){alias    T ID;}
>> template getOverloads(alias f){
>>      enum fname = f.stringof[0..f.stringof.indexOf("(")];
>>      alias ID!(__traits(getOverloads, __traits(parent, f), fname)) getOverloads;
>> }
>>
>> I think this should go into std.traits, as soon as it works. (DMD is buggy when it comes to taking the .stringof of a function. It misinterprets it as a property function call in some cases but not in others. Messy.)
>
> Yeah, your version does not work with my old GDC either (stringof returns really weird
> things here...);  this one works:
>
> template ID(T...) { alias T ID; }
> template getOverloads(alias F) {
>     alias ID!(__traits(getOverloads, __traits(parent, F),
> __traits(identifier, F)))

Nice one.

> getOverloads;
> }
>
> and looks obvious enough; it would be nice to get rid of that extra ID step,
> though.
>
> artur