Jump to page: 1 2
Thread overview
Overload of ! operator
Jun 26, 2013
Eric
Jun 26, 2013
bearophile
Jun 26, 2013
Jonathan M Davis
Jun 26, 2013
cal
Jun 26, 2013
Jonathan M Davis
Jun 26, 2013
Ali Çehreli
Jun 26, 2013
Eric
Jun 26, 2013
cal
Jun 26, 2013
Jonathan M Davis
Jun 26, 2013
cal
Jun 26, 2013
Jonathan M Davis
Jun 26, 2013
Eric
Jun 26, 2013
Jonathan M Davis
Jun 26, 2013
monarch_dodra
June 26, 2013
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
June 26, 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
June 26, 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
June 26, 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.
>
> -Eric

According 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).
June 26, 2013
On Wednesday, June 26, 2013 05:35:03 cal wrote:
> 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.
> > 
> > -Eric
> 
> According 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).

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 Davis
June 26, 2013
On 06/25/2013 09:05 PM, Jonathan M Davis wrote:

> On Wednesday, June 26, 2013 05:35:03 cal wrote:
>> 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.
>>>
>>> -Eric
>>
>> According 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).
>
> 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).

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 to
> work

It surprisingly works both with opCast and 'alias this'.

Ali

June 26, 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:
>
> > On Wednesday, June 26, 2013 05:35:03 cal wrote:
> >> 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.
> >>>
> >>> -Eric
> >>
> >> According 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).
> >
> > 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).
>
> 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 to
> > work
>
> It surprisingly works both with opCast and 'alias this'.
>
> Ali


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.

-Eric








June 26, 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?
June 26, 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:
> > 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?

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 Davis
June 26, 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:
>> 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?
>
> 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 Davis

But that code I posted does work, and gives the output shown. Am I misunderstanding?
« First   ‹ Prev
1 2