digitalmars.D - Annoyance with function template unwrapping
- solidstate1991 (28/28) Jan 16 2021 In one of my projects, I want to use function pointers that I get
- Basile B. (18/46) Jan 16 2021 It's not a bug. If you rewrite the function without the shorthand
- solidstate1991 (3/11) Jan 16 2021 This one didn't work for me, since it couldn't find the function
- kdevel (20/32) Jan 17 2021 On Saturday, 16 January 2021 at 22:09:48 UTC, solidstate1991
- Paul Backus (14/18) Jan 17 2021 It's not exactly a one-declaration rule. Templates, like
In one of my projects, I want to use function pointers that I get from a function template that has overloads. Easily reproducable example: void func(ubyte b)(int i) { writeln(__PRETTY_FUNCTION__); } void func(ubyte b)(float f) { writeln(__PRETTY_FUNCTION__); } void main() { void function(float) fp = &func!(5); // Error: template onlineapp.func matches more than one template declaration } However defining the function templates this way works: template func(ubyte b) { void func(int i) { writeln(__PRETTY_FUNCTION__); } void func(float i) { writeln(__PRETTY_FUNCTION__); } } I might change my project CPUblit to fit to the latter, and then add unittests to ensure that it works, but I don't know whether it's a bug, some odd behavior, or something DIP-worthy.
Jan 16 2021
On Saturday, 16 January 2021 at 22:09:48 UTC, solidstate1991 wrote:In one of my projects, I want to use function pointers that I get from a function template that has overloads. Easily reproducable example: void func(ubyte b)(int i) { writeln(__PRETTY_FUNCTION__); } void func(ubyte b)(float f) { writeln(__PRETTY_FUNCTION__); } void main() { void function(float) fp = &func!(5); // Error: template onlineapp.func matches more than one template declaration } However defining the function templates this way works: template func(ubyte b) { void func(int i) { writeln(__PRETTY_FUNCTION__); } void func(float i) { writeln(__PRETTY_FUNCTION__); } } I might change my project CPUblit to fit to the latter, and then add unittests to ensure that it works, but I don't know whether it's a bug, some odd behavior, or something DIP-worthy.It's not a bug. If you rewrite the function without the shorthand syntax then you realize that the error message is correct, there's indeed two "template func(){}". As a workaround, you can build the overlaod set explicitly, e.g void func1(ubyte b)(float f) { } void func2(ubyte b)(int i) { } alias func = func1!5; alias func = func2!5; or the same but "meta-programmatically" void f(ubyte b)(float f) { } void f(ubyte b)(int i) { } static foreach (o; __traits(getOverloads, mixin(__MODULE__), "func", true)) alias func = o!5; which allows to use a single ident for all the template func, although the overload set must be named differently.
Jan 16 2021
On Saturday, 16 January 2021 at 23:19:41 UTC, Basile B. wrote:or the same but "meta-programmatically" void f(ubyte b)(float f) { } void f(ubyte b)(int i) { } static foreach (o; __traits(getOverloads, mixin(__MODULE__), "func", true)) alias func = o!5; which allows to use a single ident for all the template func, although the overload set must be named differently.This one didn't work for me, since it couldn't find the function once I tried to use them from an external package.
Jan 16 2021
On Saturday, 16 January 2021 at 22:09:48 UTC, solidstate1991 wrote: [...]However defining the function templates this way works: template func(ubyte b) { void func(int i) { writeln(__PRETTY_FUNCTION__); } void func(float i) { writeln(__PRETTY_FUNCTION__); } }Fits.I might change my project CPUblit to fit to the latter, and then add unittests to ensure that it works, but I don't know whether it's a bug, some odd behavior, or something DIP-worthy.It's odd behavior. It seems that in D template definitions are things in itself (like a struct definition) which obey a one declaration (!) rule. template S (T) { void foo () {} } template S (T) { void bar () {} } auto fp = &S!int.bar; depicts the programmer's intent in a crystal clear manner. Nonetheless dmd yiels the error you encountered. I think that D-templates should behave like C++ namespaces not like structs.
Jan 17 2021
On Sunday, 17 January 2021 at 18:36:13 UTC, kdevel wrote:It's odd behavior. It seems that in D template definitions are things in itself (like a struct definition) which obey a one declaration (!) rule.It's not exactly a one-declaration rule. Templates, like functions, can be overloaded: template foo(T) { enum foo = "overload one"; } template foo(T, U) { enum foo = "overload two"; } static assert(foo!int == "overload one"); static assert(foo!(int, double) == "overload two"); As long as the overloads are unambiguous, there's no problem. As with functions, it's only when you have two overloads that match the same arguments that you get an error.
Jan 17 2021
On Sunday, 17 January 2021 at 19:29:59 UTC, Paul Backus wrote: [...]As long as the overloads are unambiguous, there's no problem. As with functions, it's only when you have two overloads that match the same arguments that you get an error.And sometimes you don't get an error: ```temploverl.d template S (U) { int x = 1; } template S (U, V = void) { int x = 2; } int main () { import std.stdio: writeln; writeln (S!(int).x); return 0; } ``` $ dmd temploverl $ ./temploverl 2
Jan 17 2021
On Sunday, 17 January 2021 at 20:03:46 UTC, kdevel wrote:$ dmd temploverl $ ./temploverl 2Erratum: 1, not 2 is printed.
Jan 17 2021