digitalmars.D.learn - Address of overloaded functions
- John Colvin (10/10) Jul 03 2013 Is there any way to take the address of any of an overloaded set
- Artur Skawina (3/15) Jul 03 2013 void function(long) b = &foo;
- John Colvin (2/18) Jul 03 2013 Thanks, that works
- H. S. Teoh (5/26) Jul 03 2013 This is interesting. How does C++ handle this? (Or does it?)
- Artur Skawina (4/28) Jul 03 2013 The same - the context determines which overload is chosen, and
- H. S. Teoh (10/38) Jul 03 2013 Oh, so it tells the difference by whether you write
- Artur Skawina (7/47) Jul 03 2013 Yep. Things like
- H. S. Teoh (7/58) Jul 03 2013 [...]
- Artur Skawina (16/22) Jul 03 2013 Real Programmers need no special syntax :)
- Tyro[17] (15/24) Jul 03 2013 Often I see terse demonstrations of ingenious ways of doing things in
- Artur Skawina (44/59) Jul 04 2013 Any time you need a pointer to an overloaded symbol - it's not possible
- H. S. Teoh (10/31) Jul 03 2013 Wow. I didn't know you could use A.init for variadic A... !
- Artur Skawina (7/15) Jul 03 2013 At some point somebody is going to ask for
- H. S. Teoh (7/26) Jul 03 2013 [...]
- Artur Skawina (9/33) Jul 03 2013 Like i said - not right now. Extending UFCS to be explicit can be done,
- Dicebot (2/12) Jul 03 2013 http://dpaste.dzfl.pl/1e705a3b
- John Colvin (3/18) Jul 03 2013 It's a pity that only work within an aggregate (the documentation
- Artur Skawina (3/21) Jul 03 2013 http://forum.dlang.org/thread/xamuenbcabnhrtqjjizw@forum.dlang.org#post-...
- Dicebot (3/5) Jul 04 2013 http://dpaste.dzfl.pl/6866e094
- John Colvin (2/7) Jul 04 2013 Hooray :) I've submitted a pull request to fix the documentation.
- Artur Skawina (6/21) Jul 03 2013 And if you meant for the overload resolution to happen at call-time,
Is there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }
Jul 03 2013
On 07/03/13 16:52, John Colvin wrote:Is there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }void function(long) b = &foo; artur
Jul 03 2013
On Wednesday, 3 July 2013 at 15:03:46 UTC, Artur Skawina wrote:On 07/03/13 16:52, John Colvin wrote:Thanks, that worksIs there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }void function(long) b = &foo; artur
Jul 03 2013
On Wed, Jul 03, 2013 at 05:15:48PM +0200, John Colvin wrote:On Wednesday, 3 July 2013 at 15:03:46 UTC, Artur Skawina wrote:This is interesting. How does C++ handle this? (Or does it?) T -- Debian GNU/Linux: Cray on your desktop.On 07/03/13 16:52, John Colvin wrote:Thanks, that worksIs there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }void function(long) b = &foo; artur
Jul 03 2013
On 07/03/13 17:27, H. S. Teoh wrote:On Wed, Jul 03, 2013 at 05:15:48PM +0200, John Colvin wrote:The same - the context determines which overload is chosen, and ambiguity is an error. arturOn Wednesday, 3 July 2013 at 15:03:46 UTC, Artur Skawina wrote:This is interesting. How does C++ handle this? (Or does it?)On 07/03/13 16:52, John Colvin wrote:Thanks, that worksIs there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }void function(long) b = &foo; artur
Jul 03 2013
On Wed, Jul 03, 2013 at 05:41:25PM +0200, Artur Skawina wrote:On 07/03/13 17:27, H. S. Teoh wrote:Oh, so it tells the difference by whether you write void (*p)(int) = foo; or void (*p)(long) = foo; ? I guess that makes sense. T -- There are 10 kinds of people in the world: those who can count in binary, and those who can't.On Wed, Jul 03, 2013 at 05:15:48PM +0200, John Colvin wrote:The same - the context determines which overload is chosen, and ambiguity is an error.On Wednesday, 3 July 2013 at 15:03:46 UTC, Artur Skawina wrote:This is interesting. How does C++ handle this? (Or does it?)On 07/03/13 16:52, John Colvin wrote:Thanks, that worksIs there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }void function(long) b = &foo; artur
Jul 03 2013
On 07/03/13 17:43, H. S. Teoh wrote:On Wed, Jul 03, 2013 at 05:41:25PM +0200, Artur Skawina wrote:Yep. Things like void c(void (*fp)(long), long a) { fp(a); } c(foo, 2); work as expected too.On 07/03/13 17:27, H. S. Teoh wrote:Oh, so it tells the difference by whether you write void (*p)(int) = foo; or void (*p)(long) = foo; ?On Wed, Jul 03, 2013 at 05:15:48PM +0200, John Colvin wrote:The same - the context determines which overload is chosen, and ambiguity is an error.On Wednesday, 3 July 2013 at 15:03:46 UTC, Artur Skawina wrote:This is interesting. How does C++ handle this? (Or does it?)On 07/03/13 16:52, John Colvin wrote:Thanks, that worksIs there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }void function(long) b = &foo; arturI guess that makes sense.The context dependence isn't ideal, but what's the alternative?... artur
Jul 03 2013
On Wed, Jul 03, 2013 at 06:07:07PM +0200, Artur Skawina wrote:On 07/03/13 17:43, H. S. Teoh wrote:[...] Explicit syntax for specifying overloads? ;-) Not like that would happen in D, though. T -- Error: Keyboard not attached. Press F1 to continue. -- Yoon Ha Lee, CONLANGOn Wed, Jul 03, 2013 at 05:41:25PM +0200, Artur Skawina wrote:Yep. Things like void c(void (*fp)(long), long a) { fp(a); } c(foo, 2); work as expected too.On 07/03/13 17:27, H. S. Teoh wrote:Oh, so it tells the difference by whether you write void (*p)(int) = foo; or void (*p)(long) = foo; ?On Wed, Jul 03, 2013 at 05:15:48PM +0200, John Colvin wrote:The same - the context determines which overload is chosen, and ambiguity is an error.On Wednesday, 3 July 2013 at 15:03:46 UTC, Artur Skawina wrote:This is interesting. How does C++ handle this? (Or does it?)On 07/03/13 16:52, John Colvin wrote:Thanks, that worksIs there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }void function(long) b = &foo; arturI guess that makes sense.The context dependence isn't ideal, but what's the alternative?...
Jul 03 2013
On 07/03/13 18:24, H. S. Teoh wrote:On Wed, Jul 03, 2013 at 06:07:07PM +0200, Artur Skawina wrote:Real Programmers need no special syntax :) import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } auto pickOverload(alias FP, A...)() property { typeof(FP(A.init)) function(A) fp = &FP; return fp;} void main() { auto b = pickOverload!(foo, long); b(2); } But using the context to automatically figure out the right overload make some things easier; it's just that eg the lhs of an assignment affecting the result of the rhs-expression doesn't /feel/ right. arturThe context dependence isn't ideal, but what's the alternative?...[...] Explicit syntax for specifying overloads? ;-) Not like that would happen in D, though.
Jul 03 2013
On 7/3/13 12:52 PM, Artur Skawina wrote:import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } auto pickOverload(alias FP, A...)() property { typeof(FP(A.init)) function(A) fp = &FP; return fp;} void main() { auto b = pickOverload!(foo, long); b(2); }Often I see terse demonstrations of ingenious ways of doing things in the language but am at a lost as with regards to under what circumstances on would use such a feature. This happens to be one of those cases. Could you provide a couple circumstances where this would prove useful/handy? Thanks, -- Andrew Edwards -------------------- http://www.akeron.co auto getAddress() { string location = " ", period = "."; return ("info" ~ location ~ "afidem" ~ period ~ "org"); }
Jul 03 2013
On 07/04/13 01:31, Tyro[17] wrote:On 7/3/13 12:52 PM, Artur Skawina wrote:Any time you need a pointer to an overloaded symbol - it's not possible to simply take its address, because there isn't enough information to tell which function you're interested in. Overload resolution happens at the call site (by matching the argument list); if you're not calling the function you need another mechanism to disambiguate. When taking an address of an overloaded function C++ (and D) selects the right one by looking at the context, ie the "target". But that means that you need to know the exact signature of the function - which isn't necessarily the case, especially with D's auto and templates. For example, you may not care what the return type is; in D a type name can easily be longer than a page, or require `typeof()`, so it can also be hard if not impossible to write down. "pickOverload" lets you ignore all the uninteresting details - the compiler already knows them - you only have specify the arguments you intend to call the function pointer with. Actually, while context alone is mostly enough for std-C++-w/o-extensions, it's not really enough for D - eg the above pickOverload implementation will lose the function attributes and linkage. Which is a much bigger problem in D because " safe" etc are often inferred. It's unreasonable to require the type of the "b" variable to always be up-to-date, when foo's signature can be changing relatively often, or even be unpredictable, like when the code is inside a template. So a better pickOverload implementation would be: template ID(T...) { alias T ID; } template getOverloads(alias F) { alias getOverloads = ID!(__traits(getOverloads, __traits(parent, F), __traits(identifier, F))); } auto pickOverload(alias F, A...)() property { static if (__traits(compiles, function(){typeof(F(A.init)) function(A) fp = &F;})) enum typeof(F(A.init)) function(A) fp = &F; else static if (__traits(compiles, function(){extern (C) typeof(F(A.init)) function(A) fp = &F;})) extern (C) enum typeof(F(A.init)) function(A) fp = &F; foreach (O; getOverloads!F) static if (is(typeof(&O==fp))) if (&O==fp) return &O; assert(0); } This now no longer loses information and works with safe/pure etc code. But it's anything but obvious, and extending it to handle other calling conventions wouldn't scale. Hence a trait that does the overload resolution and returns the chosen one would be a better idea. arturimport std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } auto pickOverload(alias FP, A...)() property { typeof(FP(A.init)) function(A) fp = &FP; return fp;} void main() { auto b = pickOverload!(foo, long); b(2); }Often I see terse demonstrations of ingenious ways of doing things in the language but am at a lost as with regards to under what circumstances on would use such a feature. This happens to be one of those cases. Could you provide a couple circumstances where this would prove useful/handy?
Jul 04 2013
On Wed, Jul 03, 2013 at 06:52:56PM +0200, Artur Skawina wrote:On 07/03/13 18:24, H. S. Teoh wrote:Wow. I didn't know you could use A.init for variadic A... ! That's amazing. D rawkz!!On Wed, Jul 03, 2013 at 06:07:07PM +0200, Artur Skawina wrote:Real Programmers need no special syntax :) import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } auto pickOverload(alias FP, A...)() property { typeof(FP(A.init)) function(A) fp = &FP; return fp;}The context dependence isn't ideal, but what's the alternative?...[...] Explicit syntax for specifying overloads? ;-) Not like that would happen in D, though.void main() { auto b = pickOverload!(foo, long);Now *that's* what I call coolness. Self-documenting and convenient to use (though in this case it's arguable whether it's actually better than native syntax).b(2); }[...] T -- What doesn't kill me makes me stranger.
Jul 03 2013
On 07/03/13 21:02, H. S. Teoh wrote:On Wed, Jul 03, 2013 at 06:52:56PM +0200, Artur Skawina wrote:At some point somebody is going to ask for auto b = foo.pickOverload!(long) with a better name for 'pickOverload'. :) Which actually is possible, but would need sane optional-() and UFCS models. Ie not right now. arturvoid main() { auto b = pickOverload!(foo, long);Now *that's* what I call coolness. Self-documenting and convenient to use (though in this case it's arguable whether it's actually better than native syntax).
Jul 03 2013
On Wed, Jul 03, 2013 at 10:10:08PM +0200, Artur Skawina wrote:On 07/03/13 21:02, H. S. Teoh wrote:[...] I don't think UFCS applies to compile-time arguments? So this wouldn't work. T -- There's light at the end of the tunnel. It's the oncoming train.On Wed, Jul 03, 2013 at 06:52:56PM +0200, Artur Skawina wrote:At some point somebody is going to ask for auto b = foo.pickOverload!(long) with a better name for 'pickOverload'. :) Which actually is possible, but would need sane optional-() and UFCS models. Ie not right now.void main() { auto b = pickOverload!(foo, long);Now *that's* what I call coolness. Self-documenting and convenient to use (though in this case it's arguable whether it's actually better than native syntax).
Jul 03 2013
On 07/03/13 22:44, H. S. Teoh wrote:On Wed, Jul 03, 2013 at 10:10:08PM +0200, Artur Skawina wrote:Like i said - not right now. Extending UFCS to be explicit can be done, and is a good idea for other reasons. Once something like that exists then the problem is the 'foo' symbol -- that's why the optional-parens get in the way. I'm just saying that doing that might be possible, not that it will happen in the current D incarnation. For some reason some people seem to like the optional parens. :^) arturOn 07/03/13 21:02, H. S. Teoh wrote:[...] I don't think UFCS applies to compile-time arguments? So this wouldn't work.On Wed, Jul 03, 2013 at 06:52:56PM +0200, Artur Skawina wrote:At some point somebody is going to ask for auto b = foo.pickOverload!(long) with a better name for 'pickOverload'. :) Which actually is possible, but would need sane optional-() and UFCS models. Ie not right now.void main() { auto b = pickOverload!(foo, long);Now *that's* what I call coolness. Self-documenting and convenient to use (though in this case it's arguable whether it's actually better than native syntax).
Jul 03 2013
On Wednesday, 3 July 2013 at 14:52:32 UTC, John Colvin wrote:Is there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }http://dpaste.dzfl.pl/1e705a3b
Jul 03 2013
On Wednesday, 3 July 2013 at 15:05:00 UTC, Dicebot wrote:On Wednesday, 3 July 2013 at 14:52:32 UTC, John Colvin wrote:It's a pity that only work within an aggregate (the documentation actually says only classes)Is there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }http://dpaste.dzfl.pl/1e705a3b
Jul 03 2013
On 07/03/13 17:17, John Colvin wrote:On Wednesday, 3 July 2013 at 15:05:00 UTC, Dicebot wrote:http://forum.dlang.org/thread/xamuenbcabnhrtqjjizw forum.dlang.org#post-mailman.1122.1332633715.4860.digitalmars-d-learn:40puremagic.com arturOn Wednesday, 3 July 2013 at 14:52:32 UTC, John Colvin wrote:It's a pity that only work within an aggregate (the documentation actually says only classes)Is there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }http://dpaste.dzfl.pl/1e705a3b
Jul 03 2013
On Wednesday, 3 July 2013 at 15:17:49 UTC, John Colvin wrote:It's a pity that only work within an aggregate (the documentation actually says only classes)http://dpaste.dzfl.pl/6866e094 Surprise! :P
Jul 04 2013
On Thursday, 4 July 2013 at 09:15:30 UTC, Dicebot wrote:On Wednesday, 3 July 2013 at 15:17:49 UTC, John Colvin wrote:Hooray :) I've submitted a pull request to fix the documentation.It's a pity that only work within an aggregate (the documentation actually says only classes)http://dpaste.dzfl.pl/6866e094 Surprise! :P
Jul 04 2013
On 07/03/13 17:03, Artur Skawina wrote:On 07/03/13 16:52, John Colvin wrote:And if you meant for the overload resolution to happen at call-time, that's obviously not directly possible - there's no address of a /set/ of functions. You can use an alias, though: alias b = foo; arturIs there any way to take the address of any of an overloaded set of functions? import std.stdio; void foo(int a){ writeln("overload int"); } void foo(long b){ writeln("overload long"); } void main() { auto b = &foo; //ambiguous => error b(2); //valid for either overload }void function(long) b = &foo;
Jul 03 2013