digitalmars.D.learn - Overload of ! operator
- Eric (4/4) Jun 25 2013 Is there a way to overload the ! operator? I can't seem to get
- bearophile (7/11) Jun 25 2013 D is not a superset of C++ and I think there is no way to
- Jonathan M Davis (6/9) Jun 25 2013 TDPL does not list it as an overloadable operator, so it probably can't ...
- cal (6/11) Jun 25 2013 According to http://dlang.org/operatoroverloading.html#Cast, the
- Jonathan M Davis (8/23) Jun 25 2013 Yeah, that should work for the conditions in if, while, and for loops bu...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (36/56) Jun 25 2013 sure).
- Eric (13/73) Jun 25 2013 Thanks for all the insignt. But I think I'm just going to fudge
- cal (16/23) Jun 25 2013 ...
- Jonathan M Davis (16/45) Jun 25 2013 No, it's not. That would require an implicit cast (which requires using ...
- cal (4/56) Jun 25 2013 But that code I posted does work, and gives the output shown. Am
- Jonathan M Davis (10/12) Jun 25 2013 Then my understanding of how ! is handled is wrong. Apparently !s does g...
- Eric (4/27) Jun 25 2013 I should have also added that the overloaded ! method returns a
- Jonathan M Davis (16/18) Jun 25 2013 Well, at that point, you're completely out of luck with regards to overl...
- monarch_dodra (18/49) Jun 25 2013 Yeah, basically, you define:
Is there a way to overload the ! operator? I can't seem to get it to work with the standard unaryOp method. I need this because I am making a wrapper for a C++ API that has ! overloaded. -Eric
Jun 25 2013
Eric:Is there a way to overload the ! operator? I can't seem to get it to work with the standard unaryOp method. I need this because I am making a wrapper for a C++ API that has ! overloaded.D is not a superset of C++ and I think there is no way to overload the ! alone. This is by design. But you can define a "bang" property method. Maybe other people can give you a better answer. Bye, bearophile
Jun 25 2013
On Wednesday, June 26, 2013 04:50:44 Eric wrote:Is there a way to overload the ! operator? I can't seem to get it to work with the standard unaryOp method. I need this because I am making a wrapper for a C++ API that has ! overloaded.TDPL does not list it as an overloadable operator, so it probably can't be overloaded (especially if you've tried it, and it doesn't work). But you should be able to simply have a wrapper function which is a normal function rather than an overloaded operator. - Jonathan M Davis
Jun 25 2013
On Wednesday, 26 June 2013 at 02:50:51 UTC, Eric wrote:Is there a way to overload the ! operator? I can't seem to get it to work with the standard unaryOp method. I need this because I am making a wrapper for a C++ API that has ! overloaded. -EricAccording to http://dlang.org/operatoroverloading.html#Cast, the following are rewritten: if (e) => if (e.opCast!(bool)) if (!e) => if (!e.opCast!(bool)) So perhaps you need to override opCast!(bool).
Jun 25 2013
On Wednesday, June 26, 2013 05:35:03 cal wrote:On Wednesday, 26 June 2013 at 02:50:51 UTC, Eric wrote:Yeah, that should work for the conditions in if, while, and for loops but won't work for anything else (_maybe_ ternary operators, but I'm not sure). So, if you need to be able to do !obj in the general case, that's not going to work, but if you only need it for conditions, then it would. And of course this all assumes that the C++ code is overloading ! to do something sane with bool rather than redefining it to mean something completely different. - Jonathan M DavisIs there a way to overload the ! operator? I can't seem to get it to work with the standard unaryOp method. I need this because I am making a wrapper for a C++ API that has ! overloaded. -EricAccording to http://dlang.org/operatoroverloading.html#Cast, the following are rewritten: if (e) => if (e.opCast!(bool)) if (!e) => if (!e.opCast!(bool)) So perhaps you need to override opCast!(bool).
Jun 25 2013
On 06/25/2013 09:05 PM, Jonathan M Davis wrote:On Wednesday, June 26, 2013 05:35:03 cal wrote:sure). Works for ternary as well. The other option is 'alias this' but it is a little dangerous because bool is an arithmetic type. So, opCast would be better. import std.stdio; struct S { int i; bool truth() const { return i == 42; } alias truth this; } void foo(bool b) { writeln(b); } void main() { auto s = S(42); if (s){ } while (s) { break; } int i = s ? 4 : 5; foo(s); // What does it mean? writeln(s + 2); writeln(!s - 7); }On Wednesday, 26 June 2013 at 02:50:51 UTC, Eric wrote:Yeah, that should work for the conditions in if, while, and for loops but won't work for anything else (_maybe_ ternary operators, but I'm notIs there a way to overload the ! operator? I can't seem to get it to work with the standard unaryOp method. I need this because I am making a wrapper for a C++ API that has ! overloaded. -EricAccording to http://dlang.org/operatoroverloading.html#Cast, the following are rewritten: if (e) => if (e.opCast!(bool)) if (!e) => if (!e.opCast!(bool)) So perhaps you need to override opCast!(bool).So, if you need to be able to do !obj in the general case, that's notgoing toworkIt surprisingly works both with opCast and 'alias this'. Ali
Jun 25 2013
On Wednesday, 26 June 2013 at 04:16:30 UTC, Ali Çehreli wrote:On 06/25/2013 09:05 PM, Jonathan M Davis wrote:Thanks for all the insignt. But I think I'm just going to fudge this one with a "bang()" method... Incidently, for this project I figured out an interesting use of alias. The C++ classes I am wrapping have a lot of virtual methods with all primitive arguments. So I create an D-interface for them, and wrap the rest with C methods. The wrapper class then makes methods that call the C methods, and then aliases the interface reference to "this" so that the wrapper class instance points to both the C++ native methods as well as the C-wrapped methods. -EricOn Wednesday, June 26, 2013 05:35:03 cal wrote:getOn Wednesday, 26 June 2013 at 02:50:51 UTC, Eric wrote:Is there a way to overload the ! operator? I can't seem totheit to work with the standard unaryOp method. I need this because I am making a wrapper for a C++ API that has ! overloaded. -EricAccording to http://dlang.org/operatoroverloading.html#Cast,for loops butfollowing are rewritten: if (e) => if (e.opCast!(bool)) if (!e) => if (!e.opCast!(bool)) So perhaps you need to override opCast!(bool).Yeah, that should work for the conditions in if, while, andwon't work for anything else (_maybe_ ternary operators, butI'm not sure). Works for ternary as well. The other option is 'alias this' but it is a little dangerous because bool is an arithmetic type. So, opCast would be better. import std.stdio; struct S { int i; bool truth() const { return i == 42; } alias truth this; } void foo(bool b) { writeln(b); } void main() { auto s = S(42); if (s){ } while (s) { break; } int i = s ? 4 : 5; foo(s); // What does it mean? writeln(s + 2); writeln(!s - 7); }So, if you need to be able to do !obj in the general case,that's not going toworkIt surprisingly works both with opCast and 'alias this'. Ali
Jun 25 2013
On Wednesday, 26 June 2013 at 04:06:05 UTC, Jonathan M Davis wrote:Yeah, that should work for the conditions in if, while, and for loops but won't work for anything else (_maybe_ ternary operators, but I'm not sure). So, if you need to be able to do !obj in the general case, that's not going to work... import std.stdio; struct S { int x; bool opCast(T)() if (is(T == bool)) { return x == 0; } } void main() { auto s = S(1); auto b = !s; writeln(b); // true } Is this not supposed to work?
Jun 25 2013
On Wednesday, June 26, 2013 06:59:14 cal wrote:On Wednesday, 26 June 2013 at 04:06:05 UTC, Jonathan M Davis wrote:No, it's not. That would require an implicit cast (which requires using alias this). opCast gives you an explicit cast only. Where that becomes confusing is the fact that the compiler inserts explicitly casts to bool in conditions for if statements, loops, and the ternary operator. e.g. if(foo) {...} becomes if(cast(bool)foo) {...} So, if you've overloaded opCast to bool, then it'll get used in the conditions for if statements, loops, and the ternary operator. But no explicit cast is added just for putting ! in front of a variable. It works with something like if(!foo) {...} simply because that becomes if(!cast(bool)foo) {...} But nothing special is done for !, and !a will not call opCast. - Jonathan M DavisYeah, that should work for the conditions in if, while, and for loops but won't work for anything else (_maybe_ ternary operators, but I'm not sure). So, if you need to be able to do !obj in the general case, that's not going to work... import std.stdio; struct S { int x; bool opCast(T)() if (is(T == bool)) { return x == 0; } } void main() { auto s = S(1); auto b = !s; writeln(b); // true } Is this not supposed to work?
Jun 25 2013
On Wednesday, 26 June 2013 at 05:08:07 UTC, Jonathan M Davis wrote:On Wednesday, June 26, 2013 06:59:14 cal wrote:But that code I posted does work, and gives the output shown. Am I misunderstanding?On Wednesday, 26 June 2013 at 04:06:05 UTC, Jonathan M Davis wrote:No, it's not. That would require an implicit cast (which requires using alias this). opCast gives you an explicit cast only. Where that becomes confusing is the fact that the compiler inserts explicitly casts to bool in conditions for if statements, loops, and the ternary operator. e.g. if(foo) {...} becomes if(cast(bool)foo) {...} So, if you've overloaded opCast to bool, then it'll get used in the conditions for if statements, loops, and the ternary operator. But no explicit cast is added just for putting ! in front of a variable. It works with something like if(!foo) {...} simply because that becomes if(!cast(bool)foo) {...} But nothing special is done for !, and !a will not call opCast. - Jonathan M DavisYeah, that should work for the conditions in if, while, and for loops but won't work for anything else (_maybe_ ternary operators, but I'm not sure). So, if you need to be able to do !obj in the general case, that's not going to work... import std.stdio; struct S { int x; bool opCast(T)() if (is(T == bool)) { return x == 0; } } void main() { auto s = S(1); auto b = !s; writeln(b); // true } Is this not supposed to work?
Jun 25 2013
On Wednesday, June 26, 2013 07:14:36 cal wrote:But that code I posted does work, and gives the output shown. Am I misunderstanding?Then my understanding of how ! is handled is wrong. Apparently !s does get replaced with !cast(bool)s, or it couldn't work. But note that bool b = s; doesn't work, so as I said, it's not the case that opCast gives you an implicit cast. It's just the cases where cases where the compiler inserts an explicit cast for you that it looks like it gives you an implicit cast. But apparently, there was a case that it inserts an explicit cast of which I was not aware. - Jonathan M Davis
Jun 25 2013
On Wednesday, 26 June 2013 at 04:59:19 UTC, cal wrote:On Wednesday, 26 June 2013 at 04:06:05 UTC, Jonathan M Davis wrote:I should have also added that the overloaded ! method returns a class instance and not a bool. -EricYeah, that should work for the conditions in if, while, and for loops but won't work for anything else (_maybe_ ternary operators, but I'm not sure). So, if you need to be able to do !obj in the general case, that's not going to work... import std.stdio; struct S { int x; bool opCast(T)() if (is(T == bool)) { return x == 0; } } void main() { auto s = S(1); auto b = !s; writeln(b); // true } Is this not supposed to work?
Jun 25 2013
On Wednesday, June 26, 2013 07:15:19 Eric wrote:I should have also added that the overloaded ! method returns a class instance and not a bool.Well, at that point, you're completely out of luck with regards to overloading !. In general, D doesn't really support overloading operators in a manner that doesn't match how the built-in types work. It does things like assume that <, <=, >=, and > will act the same way that they do with the built-in types and uses opCmp to extrapolate all of those operators. In some cases, you _can_ make overloaded operators return types that make it so that they don't function anything like the built-in types (e.g. opBinary with + could return a completely unrelated type that had nothing to do with the original type or with addition), but in pretty much any case where the compiler can get away with using the same overloaded operator for multiple operators, it does it. So, a number of decisions were made to better support correctness with types that actually try and overload operators to match what the built-in types do without caring about how that would affect types that would try and overload them to do unrelated stuff. - Jonathan M Davis
Jun 25 2013
On Wednesday, 26 June 2013 at 05:29:49 UTC, Jonathan M Davis wrote:On Wednesday, June 26, 2013 07:15:19 Eric wrote:Yeah, basically, you define: * opCast(bool) //to test both "true" and "false" * opEqual //test equality (both == and !=) * opCmp //Comparison (< > <= >=) And everything gets defined from these. It also works that way for operators: op++ is defined in terms or ++op. And if you define "op+", then defining op++ becomes entirely optional! This is a cool feature, although there are those *very* rare cases where it gets in your way. For example, the other day, I was trying to implement a "tribool": http://www.boost.org/doc/libs/1_53_0/doc/html/tribool/tutorial.html It did not work, I mean: AT ALL! This is because for a tribool, being "not true" does not imply being "false"...I should have also added that the overloaded ! method returns a class instance and not a bool.Well, at that point, you're completely out of luck with regards to overloading !. In general, D doesn't really support overloading operators in a manner that doesn't match how the built-in types work. It does things like assume that <, <=, >=, and > will act the same way that they do with the built-in types and uses opCmp to extrapolate all of those operators. In some cases, you _can_ make overloaded operators return types that make it so that they don't function anything like the built-in types (e.g. opBinary with + could return a completely unrelated type that had nothing to do with the original type or with addition), but in pretty much any case where the compiler can get away with using the same overloaded operator for multiple operators, it does it. So, a number of decisions were made to better support correctness with types that actually try and overload operators to match what the built-in types do without caring about how that would affect types that would try and overload them to do unrelated stuff. - Jonathan M Davis
Jun 25 2013