digitalmars.D.learn - How to call opCall as template?
- Namespace (38/38) Jan 30 2014 Here: http://dlang.org/operatoroverloading.html#FunctionCall
- Stanislav Blinov (1/10) Jan 30 2014 f.opCall!float(6, 7, 8);
- Namespace (4/15) Jan 30 2014 ... Yes, of course. But where is the sense to use opCall if I
- Frustrated (3/19) Jan 30 2014 Could you not use opDispatch? Not sure if you can templatize it
- Namespace (2/22) Jan 30 2014 Example? I did not know how.
- Frustrated (22/45) Jan 30 2014 doesn't seem to work with templates, I suppose you could try and
- Meta (2/40) Jan 30 2014 This is probably a bug. You should file it in Bugzilla.
- Frustrated (6/6) Jan 30 2014 Also,
- Namespace (3/9) Jan 30 2014 opDispatch is called if you try to call a non existing member.
- Frustrated (3/16) Jan 30 2014 Right, but maybe you can use the same technique as in the archive
- Frustrated (6/6) Jan 30 2014 BTW,
- Namespace (3/9) Jan 30 2014 I am sure that the error is thrown before.
- Frustrated (34/34) Jan 30 2014 import std.stdio;
- Namespace (4/6) Jan 30 2014 Sure but this is not always possible. ;)
- Frustrated (5/11) Jan 30 2014 Yes, because they all are implicit. It looks like you are calling
- Namespace (36/50) Jan 30 2014 Explan it please with examples. I'm convinced that D is smarter
- Stanislav Blinov (2/2) Jan 30 2014 Ask yourself this: in regards to overload resolution, when should
- Frustrated (36/88) Jan 31 2014 no, f(42) is not a template call and f!(42) is not ambiguous
- Namespace (2/8) Jan 31 2014 I never wanted a new notation. I only want that the bug gets
- Frustrated (53/62) Jan 31 2014 Wow, that is the point! it's not a bug! You are asking for a new
- Namespace (2/65) Jan 31 2014 Are you always so aggressive? :)
- Frustrated (1/2) Jan 31 2014 Not always ;) Just when I feel like it....
- Namespace (3/51) Jan 30 2014 Ok, done:
Here: http://dlang.org/operatoroverloading.html#FunctionCall is this example: ---- import std.stdio; struct F { int opCall() { return 0; } int opCall(int x, int y, int z) { return x * y * z; } } void main() { F f; int i; i = f(); // same as i = f.opCall(); i = f(3,4,5); // same as i = f.opCall(3,4,5); } ---- And it works of course. But what if I want to templatize opCall? How can I call it? ---- import std.stdio; struct F { T opCall(T = int)(int a, int b, int c) { return cast(T)(a * b * c); } } void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } ---- Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variable
Jan 30 2014
void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } ---- Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variablef.opCall!float(6, 7, 8);
Jan 30 2014
On Thursday, 30 January 2014 at 16:24:00 UTC, Stanislav Blinov wrote:... Yes, of course. But where is the sense to use opCall if I need to call it explicitly?void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } ---- Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variablef.opCall!float(6, 7, 8);
Jan 30 2014
On Thursday, 30 January 2014 at 16:28:42 UTC, Namespace wrote:On Thursday, 30 January 2014 at 16:24:00 UTC, Stanislav Blinov wrote:Could you not use opDispatch? Not sure if you can templatize it or not though...... Yes, of course. But where is the sense to use opCall if I need to call it explicitly?void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } ---- Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variablef.opCall!float(6, 7, 8);
Jan 30 2014
On Thursday, 30 January 2014 at 16:47:46 UTC, Frustrated wrote:On Thursday, 30 January 2014 at 16:28:42 UTC, Namespace wrote:Example? I did not know how.On Thursday, 30 January 2014 at 16:24:00 UTC, Stanislav Blinov wrote:Could you not use opDispatch? Not sure if you can templatize it or not though...... Yes, of course. But where is the sense to use opCall if I need to call it explicitly?void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } ---- Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variablef.opCall!float(6, 7, 8);
Jan 30 2014
On Thursday, 30 January 2014 at 16:53:33 UTC, Namespace wrote:On Thursday, 30 January 2014 at 16:47:46 UTC, Frustrated wrote:doesn't seem to work with templates, I suppose you could try and add it as a feature request? module main; import std.stdio; interface A { void foo(); static final New() { } } class B : A { void foo() { writeln("this is B.foo"); } void opDispatch(string s, T)(int i) { writefln("C.opDispatch('%s', %s)", s, i); } } void main() { B a = new B; //a.foo(); a.test!int(3); // any *good* reason why this shouldn't work? }On Thursday, 30 January 2014 at 16:28:42 UTC, Namespace wrote:Example? I did not know how.On Thursday, 30 January 2014 at 16:24:00 UTC, Stanislav Blinov wrote:Could you not use opDispatch? Not sure if you can templatize it or not though...... Yes, of course. But where is the sense to use opCall if I need to call it explicitly?void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } ---- Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variablef.opCall!float(6, 7, 8);
Jan 30 2014
On Thursday, 30 January 2014 at 15:59:28 UTC, Namespace wrote:Here: http://dlang.org/operatoroverloading.html#FunctionCall is this example: ---- import std.stdio; struct F { int opCall() { return 0; } int opCall(int x, int y, int z) { return x * y * z; } } void main() { F f; int i; i = f(); // same as i = f.opCall(); i = f(3,4,5); // same as i = f.opCall(3,4,5); } ---- And it works of course. But what if I want to templatize opCall? How can I call it? ---- import std.stdio; struct F { T opCall(T = int)(int a, int b, int c) { return cast(T)(a * b * c); } } void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } ---- Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variableThis is probably a bug. You should file it in Bugzilla.
Jan 30 2014
Also, http://dlang.org/operatoroverloading.html#Dispatch and possible solution to your problem: http://www.digitalmars.com/d/archives/digitalmars/D/opDispatch_and_template_parameters_117095.html Couldn't get code to compile though... but if it did, it should solve your problem.
Jan 30 2014
On Thursday, 30 January 2014 at 17:46:19 UTC, Frustrated wrote:Also, http://dlang.org/operatoroverloading.html#Dispatch and possible solution to your problem: http://www.digitalmars.com/d/archives/digitalmars/D/opDispatch_and_template_parameters_117095.html Couldn't get code to compile though... but if it did, it should solve your problem.opDispatch is called if you try to call a non existing member. But in this case you don't call a member. ;)
Jan 30 2014
On Thursday, 30 January 2014 at 18:02:05 UTC, Namespace wrote:On Thursday, 30 January 2014 at 17:46:19 UTC, Frustrated wrote:Right, but maybe you can use the same technique as in the archive link? (use an eponymous template for opCall?)Also, http://dlang.org/operatoroverloading.html#Dispatch and possible solution to your problem: http://www.digitalmars.com/d/archives/digitalmars/D/opDispatch_and_template_parameters_117095.html Couldn't get code to compile though... but if it did, it should solve your problem.opDispatch is called if you try to call a non existing member. But in this case you don't call a member. ;)
Jan 30 2014
BTW, a() is replaced with a.opCall() and you can use opDispatch on it. an opCall is a member. Either approach should work if you can get that archive example to compile.
Jan 30 2014
On Thursday, 30 January 2014 at 18:11:49 UTC, Frustrated wrote:BTW, a() is replaced with a.opCall() and you can use opDispatch on it. an opCall is a member. Either approach should work if you can get that archive example to compile.I am sure that the error is thrown before. But please show me your attempts.
Jan 30 2014
import std.stdio; struct B { template opCall(T) { void opCall(T x) { writeln(x); } } } template a(T) { } void main() { B a; a(3); // works because template parameter can be deduced from arguments a.opCall!(int)(3); // same as about but explicit a!(int)(3); // works but calls template because a! refers to a template // no way to use the above syntax to initiate an opCall on a because it is template notation. // at most one might get away with a.!(int)(3) but this is invalid } You'll never be able to do a!()() for the reasons give above. At most it would have to be implemented the compiler and I doubt it will ever happen. (for example, one could have the opExclamation but then one has ambiguity, which is why ! was chosen to avoid in the first place) I think for your example, the first case works fine using deduction.
Jan 30 2014
I think for your example, the first case works fine using deduction.Sure but this is not always possible. ;) It seems that the problem occurs also with opIndex and so probably with all op* methods. See: http://forum.dlang.org/thread/bug-12043-3 https.d.puremagic.com%2Fissues%2F#post-lcegar:241ld2:241:40digitalmars.com
Jan 30 2014
On Thursday, 30 January 2014 at 21:33:09 UTC, Namespace wrote:Yes, because they all are implicit. It looks like you are calling a template. D could figure this out but I think it will end up having similar issues as >> has in C++. Is it an a templated op* on an object or is it template function call?I think for your example, the first case works fine using deduction.Sure but this is not always possible. ;) It seems that the problem occurs also with opIndex and so probably with all op* methods. See: http://forum.dlang.org/thread/bug-12043-3 https.d.puremagic.com%2Fissues%2F#post-lcegar:241ld2:241:40digitalmars.com
Jan 30 2014
On Thursday, 30 January 2014 at 22:34:52 UTC, Frustrated wrote:On Thursday, 30 January 2014 at 21:33:09 UTC, Namespace wrote:Explan it please with examples. I'm convinced that D is smarter as C++ with the '>>' problem. --- class Foo { void opCall(size_t count) { } } Foo f = new Foo(); f(42); /// no template ---- ---- class Foo { void opCall(T)(size_t count) { } } Foo f = new Foo(); f!int(42); /// template ---- No ambiguity. As far as I understand you, you mean something like this: ---- import std.stdio; class Foo { void opCall(size_t count) { writeln("F()"); } } void f(T)(size_t count) { writeln("f()"); } void main() { Foo f = new Foo(); f(42); } ---- which prints correctly "F()"Yes, because they all are implicit. It looks like you are calling a template. D could figure this out but I think it will end up having similar issues as >> has in C++. Is it an a templated op* on an object or is it template function call?I think for your example, the first case works fine using deduction.Sure but this is not always possible. ;) It seems that the problem occurs also with opIndex and so probably with all op* methods. See: http://forum.dlang.org/thread/bug-12043-3 https.d.puremagic.com%2Fissues%2F#post-lcegar:241ld2:241:40digitalmars.com
Jan 30 2014
Ask yourself this: in regards to overload resolution, when should template instantiation occur?
Jan 30 2014
On Friday, 31 January 2014 at 00:29:20 UTC, Namespace wrote:On Thursday, 30 January 2014 at 22:34:52 UTC, Frustrated wrote:no, f(42) is not a template call and f!(42) is not ambiguous because opCall is not templated. So no ambiguity here. But if you have class Foo { void opCall(T)(size_t count) { writeln("F()"); } } then do f!(42); AND had the notation you wanted to use earlier. then which f is to be called? is f!(string)(42) referring to the templates opCall? OR is f!(string)(42) calling the template(which it normally would)? The point being there can be no unambiguous way to use the template call notation with a templated opCall if the template parameter must be explicitly given. If it can be deduced then it's call looks like a normal function call and no ! is needed, and then no ambiguity. C++ had the issues where it crapped out on >>. When used in template calls, say two nested ones), one would end up with >>, which the compiler would think it was a left shift operation and not part of the template. One would always have to put a space between them to make the templates work properly. This has been recently fixed. Somewhere on the D site, Walter(I guess) explains that he chose to use ! for template call syntax because it is not used anywhere else in any ambiguous way so when you see a template call YOU know it is a template call, unambiguously. So it becomes easy to deal with semantically. So, if your notation was implemented, it would no longer be easy to know. The compiler would have to be context sensitive, which is more complex and not perfect. I doubt Walter would go for that so you'll never be able to use an explicit templated opCall... but implicit are ok.On Thursday, 30 January 2014 at 21:33:09 UTC, Namespace wrote:Explan it please with examples. I'm convinced that D is smarter as C++ with the '>>' problem. --- class Foo { void opCall(size_t count) { } } Foo f = new Foo(); f(42); /// no template ---- ---- class Foo { void opCall(T)(size_t count) { } } Foo f = new Foo(); f!int(42); /// template ---- No ambiguity. As far as I understand you, you mean something like this: ---- import std.stdio; class Foo { void opCall(size_t count) { writeln("F()"); } } void f(T)(size_t count) { writeln("f()"); } void main() { Foo f = new Foo(); f(42); } ---- which prints correctly "F()"Yes, because they all are implicit. It looks like you are calling a template. D could figure this out but I think it will end up having similar issues as >> has in C++. Is it an a templated op* on an object or is it template function call?I think for your example, the first case works fine using deduction.Sure but this is not always possible. ;) It seems that the problem occurs also with opIndex and so probably with all op* methods. See: http://forum.dlang.org/thread/bug-12043-3 https.d.puremagic.com%2Fissues%2F#post-lcegar:241ld2:241:40digitalmars.com
Jan 31 2014
So, if your notation was implemented, it would no longer be easy to know. The compiler would have to be context sensitive, which is more complex and not perfect. I doubt Walter would go for that so you'll never be able to use an explicit templated opCall... but implicit are ok.I never wanted a new notation. I only want that the bug gets fixed. :)
Jan 31 2014
On Friday, 31 January 2014 at 10:31:52 UTC, Namespace wrote:Wow, that is the point! it's not a bug! You are asking for a new notation. In your post you did F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); f is an object!!! not a template, you are calling opCall on it, right? (the last line) BUT THAT SYNTAX IS FOR TEMPLATES ONLY!!! Do you not see that if I add template f(T) { T f(int x, int y, int z) { return 3.14; } } that there is no way the compiler can know what you mean now? (again, assuming your "bug" was fixed) PAY ATTENTION!!! The following is your code with the added template I gave and two lines of yours commented out! import std.stdio; struct F { T opCall(T = int)(int a, int b, int c) { return cast(T)(a * b * c); } } void main() { //F f; //int i = f(3,4,5); float f_ = f!float(6, 7, 8); } template f(T) { T f(int x, int y, int z) { return 3.14; } } NOTE TO YOURSELF!! IT COMPILES JUST FINE!!!! I didn't change a damn thing! I'm not playing tricks or anything. the float f_ line is exactly what you gave, YET I MADE IT COMPILE WITH OUT YOUR STRUCT!!! THIS MEANS IT IS AMBIGUOUS! Your struct or my template would make it work(again, assume you could actually do what you want). This means it is impossible for the compiler to know which one you meant if we uncommented the lines. The only way it would work is if one couldn't have variables and templates use the same name at the same time in the same scope.... but this already is possible and is not ambiguous. So to fix your "bug" could break the compiler in certain circumstances. will it do it in all circumstances, no. But I doubt Walter will go for it. Not only does it look like a template call(it is in the above example), it might be hard to parse and is ambiguous in some cases. Now, maybe there is a trick to make it all work using aliases and templates but that is not the point. The point is, that the is an ambiguity because you are using the EXACT same syntax for two different things. If you can't see that then I can't help you any further.So, if your notation was implemented, it would no longer be easy to know. The compiler would have to be context sensitive, which is more complex and not perfect. I doubt Walter would go for that so you'll never be able to use an explicit templated opCall... but implicit are ok.I never wanted a new notation. I only want that the bug gets fixed. :)
Jan 31 2014
On Friday, 31 January 2014 at 11:42:54 UTC, Frustrated wrote:On Friday, 31 January 2014 at 10:31:52 UTC, Namespace wrote:Are you always so aggressive? :)Wow, that is the point! it's not a bug! You are asking for a new notation. In your post you did F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); f is an object!!! not a template, you are calling opCall on it, right? (the last line) BUT THAT SYNTAX IS FOR TEMPLATES ONLY!!! Do you not see that if I add template f(T) { T f(int x, int y, int z) { return 3.14; } } that there is no way the compiler can know what you mean now? (again, assuming your "bug" was fixed) PAY ATTENTION!!! The following is your code with the added template I gave and two lines of yours commented out! import std.stdio; struct F { T opCall(T = int)(int a, int b, int c) { return cast(T)(a * b * c); } } void main() { //F f; //int i = f(3,4,5); float f_ = f!float(6, 7, 8); } template f(T) { T f(int x, int y, int z) { return 3.14; } } NOTE TO YOURSELF!! IT COMPILES JUST FINE!!!! I didn't change a damn thing! I'm not playing tricks or anything. the float f_ line is exactly what you gave, YET I MADE IT COMPILE WITH OUT YOUR STRUCT!!! THIS MEANS IT IS AMBIGUOUS! Your struct or my template would make it work(again, assume you could actually do what you want). This means it is impossible for the compiler to know which one you meant if we uncommented the lines. The only way it would work is if one couldn't have variables and templates use the same name at the same time in the same scope.... but this already is possible and is not ambiguous. So to fix your "bug" could break the compiler in certain circumstances. will it do it in all circumstances, no. But I doubt Walter will go for it. Not only does it look like a template call(it is in the above example), it might be hard to parse and is ambiguous in some cases.So, if your notation was implemented, it would no longer be easy to know. The compiler would have to be context sensitive, which is more complex and not perfect. I doubt Walter would go for that so you'll never be able to use an explicit templated opCall... but implicit are ok.I never wanted a new notation. I only want that the bug gets fixed. :)
Jan 31 2014
Are you always so aggressive? :)Not always ;) Just when I feel like it....
Jan 31 2014
On Thursday, 30 January 2014 at 16:55:01 UTC, Meta wrote:On Thursday, 30 January 2014 at 15:59:28 UTC, Namespace wrote:Ok, done: https://d.puremagic.com/issues/show_bug.cgi?id=12043Here: http://dlang.org/operatoroverloading.html#FunctionCall is this example: ---- import std.stdio; struct F { int opCall() { return 0; } int opCall(int x, int y, int z) { return x * y * z; } } void main() { F f; int i; i = f(); // same as i = f.opCall(); i = f(3,4,5); // same as i = f.opCall(3,4,5); } ---- And it works of course. But what if I want to templatize opCall? How can I call it? ---- import std.stdio; struct F { T opCall(T = int)(int a, int b, int c) { return cast(T)(a * b * c); } } void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } ---- Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variableThis is probably a bug. You should file it in Bugzilla.
Jan 30 2014