www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Referencing an overloaded function

reply "John" <nospam unavailable.com> writes:
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.
Mar 24 2012
next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
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) {} }
Mar 24 2012
prev sibling next sibling parent Mantis <mail.mantis.88 gmail.com> writes:
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).
Mar 24 2012
prev sibling next sibling parent "John" <nospam unavailable.com> writes:
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.
Mar 24 2012
prev sibling next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
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
Mar 24 2012
prev sibling next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
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
Mar 24 2012
prev sibling next sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sat, Mar 24, 2012 at 18:07, Artur Skawina <art.08.09 gmail.com> wrote:

 =C2=A0 =C2=A0 foreach (f; __traits(getOverloads, __traits(parent, main),=


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.
Mar 24 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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.)
Mar 24 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
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

Mar 24 2012
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
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
Mar 24 2012