[Issue 24554] New: Clarrification for bad codegen on postfix operators

2024-05-17 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=24554

  Issue ID: 24554
   Summary: Clarrification for bad codegen on postfix operators
   Product: D
   Version: D2
  Hardware: All
OS: All
Status: NEW
  Severity: normal
  Priority: P1
 Component: dlang.org
  Assignee: nob...@puremagic.com
  Reporter: alphaglosi...@gmail.com

Johan Engelen asked me on the ldc bug ticket to create a ticket to find out
what the specification means.

All three compilers have differing behavior.

DMD: https://github.com/ldc-developers/ldc/issues/4651

GDC: https://forum.dlang.org/post/zybltjuxkbvtvirzw...@forum.dlang.org

ldc fe 2.107 as per run.dlang.org

```d
void main()
{
int d = 42;
bool o = d > d++;
}
```

```
define i32 @_Dmain({ i64, ptr } %unnamed) #0 {
  %d = alloca i32, align 4; [#uses = 4, size/byte = 4]
  %o = alloca i8, align 1 ; [#uses = 1, size/byte = 1]
  store i32 42, ptr %d, align 4
  %1 = load i32, ptr %d, align 4  ; [#uses = 2]
  %2 = add i32 %1, 1  ; [#uses = 1]
  store i32 %2, ptr %d, align 4
  %3 = load i32, ptr %d, align 4  ; [#uses = 1]
  %4 = icmp sgt i32 %3, %1; [#uses = 1]
  %5 = zext i1 %4 to i8   ; [#uses = 1]
  store i8 %5, ptr %o, align 1
  ret i32 0
}
```

Note; the icmp is after the add, which it shouldn't be.

Source: https://twitter.com/marcos_don/status/1787629240550150361

--


[Issue 24510] Perfect forwarding and explicit move should be compiler intrinsic and have operators

2024-04-17 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=24510

kinke  changed:

   What|Removed |Added

 CC||ki...@gmx.net

--- Comment #1 from kinke  ---
I agree that these should be intrinsics, mainly because the compiler can handle
this much much more efficiently than the template bloat of the current library
implementations. But I don't think we need new ugly operators for that, simply
keeping the self-explanatory `move` and `forward` names.

--


[Issue 24510] Perfect forwarding and explicit move should be compiler intrinsic and have operators

2024-04-16 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=24510

Bolpat  changed:

   What|Removed |Added

 CC||qs.il.paperi...@gmail.com

--


[Issue 24510] New: Perfect forwarding and explicit move should be compiler intrinsic and have operators

2024-04-16 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=24510

  Issue ID: 24510
   Summary: Perfect forwarding and explicit move should be
compiler intrinsic and have operators
   Product: D
   Version: D2
  Hardware: All
OS: All
Status: NEW
  Severity: enhancement
  Priority: P1
 Component: dmd
  Assignee: nob...@puremagic.com
  Reporter: qs.il.paperi...@gmail.com

Perfect forwarding parameters of parameters and explicit move requires
importing modules (that I have to look up every time and make no sense
naming-wise) and is quite unpleasant to look at in code. Last but not least,
the current implemenation of explicit move is ctfe-hostile, which makes no
sense as the compiler actually can move objects at ctfe. Both operations don’t
deserve that; they’re safe and useful.

My suggestion would be to make move (and forward, which boils down to either a
no-op or an explicit move) a compiler intrinsic. For both of them, there should
be unary operators: I suggest `>>` for forward and `<<` for move.

```d
f(move(x));
// becomes
f(<>xs);
// xs can be a pack!
```

They’re both unary prefix operators with the same precedence as the other unary
prefix operators.

Rationale for the operator symbols:
They look very much alike, but that’s happenstance. `>>` looks like the the
"fast forward" icon. `<<` looks like an arrow pointing away from the object and
indicates: "Whatever is in here goes out of it."

--


[Issue 11500] Bringing mixed-in operators and constructors to the overload set

2022-12-17 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=11500

Iain Buclaw  changed:

   What|Removed |Added

   Priority|P2  |P3

--


[Issue 11094] Disuniform error messages with overloaded + and ^ operators

2022-12-17 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=11094

Iain Buclaw  changed:

   What|Removed |Added

   Priority|P2  |P3

--


[Issue 9786] Allow [non-member|UFCS] implementation of operators

2022-12-17 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=9786

Iain Buclaw  changed:

   What|Removed |Added

   Priority|P2  |P4

--


[Issue 14364] Spec is incorrect for opAssign operators.

2022-12-17 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=14364

Iain Buclaw  changed:

   What|Removed |Added

   Priority|P1  |P3

--


[Issue 12559] Multi operators with template mixins produces an error

2022-12-17 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=12559

Iain Buclaw  changed:

   What|Removed |Added

   Priority|P1  |P3

--


[Issue 21124] Multiple templated is expressions used with logical operators

2022-12-17 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=21124

Iain Buclaw  changed:

   What|Removed |Added

   Priority|P1  |P4

--


Re: Blog post on keeping D1 operators for D 2.100

2022-06-24 Thread zjh via Digitalmars-d-announce
On Saturday, 11 June 2022 at 21:57:36 UTC, Steven Schveighoffer 
wrote:



https://www.schveiguy.com/blog/2022/06/how-to-keep-using-d1-operator-overloads/

-Steve


`Good article `,and [chinese 
version](https://fqbqrr.blog.csdn.net/article/details/125265063)




Blog post on keeping D1 operators for D 2.100

2022-06-11 Thread Steven Schveighoffer via Digitalmars-d-announce
D 2.100.0 removed support for D1 operator overloads. If you have a bunch 
of code that still uses them, and don't want to spend the time to 
upgrade to D2 overloads, you can still do it, using a mixin.


Here's how it works (and shows off some cool metaprogramming features of 
D): 
https://www.schveiguy.com/blog/2022/06/how-to-keep-using-d1-operator-overloads/


-Steve


[Issue 11094] Disuniform error messages with overloaded + and ^ operators

2022-05-26 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=11094

Ben  changed:

   What|Removed |Added

 CC||ben.james.jo...@gmail.com

--- Comment #2 from Ben  ---
I took a look at this, and the difference seems to be related to the extra
check(s) added at the end of the expressionsem visitors for AddExp vs XorExp:

//in xor only
if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
return setError();


A couple of questions.  This happens earlier in the visitor:

Expression e = exp.op_overload(sc);
if (e)
{
result = e;
return;
}


I assume e is null if the op overload doesn't apply (in this case there are
constness issues), but putting an error in opover.visitBin seems like maybe the
wrong fix?

Those extra checks make sense for xor, is it worth trying to add a supplemental
error or something that sees if they tried to do op overloading?

There's a TON of duplication between the addexp and xorexp visitors in
expressionsem, and I assume probably with most binop visitors.  Is it worth
trying to refactor to reduce the duplication?

--


Re: Mixin Templates and Operators

2022-04-12 Thread francesco.andreetto via Digitalmars-d-learn

On Wednesday, 6 April 2022 at 17:59:12 UTC, Adam D Ruppe wrote:

ooh yeah there's multiple here so the names don't 
overload and one on the time itself would override the ones 
from mixin template.


You'd have to alias them together on the type.


Hello Adam D Ruppe,

I see what you mean,
thank you very much for your answers!

-FA



Re: Mixin Templates and Operators

2022-04-12 Thread francesco.andreetto via Digitalmars-d-learn
On Wednesday, 6 April 2022 at 17:33:28 UTC, Steven Schveighoffer 
wrote:


As I mentioned elsewhere, it does work. But the situation I 
think must be that it's only one mixin template. Probably also 
you can't have any overloads in the type itself.


Note that I also think string mixins would work perfectly fine. 
And UFCS will never work for operator overloads, but that is by 
design.


-Steve


Hello Steve,

Thank you very much for your answers, you have been very clear 
and helpful!


-FA




Re: Mixin Templates and Operators

2022-04-12 Thread francesco.andreetto via Digitalmars-d-learn

On Wednesday, 6 April 2022 at 16:36:51 UTC, Tejas wrote:

Looks like a compiler bug, since substituting the real methods 
makes the `mixin template` code compile fine


Hi Tejas,
Thank you very much for your answer!

Also, remove the `const`, otherwise the method will word only 
on `const` instances even if the bug gets fixed


And thank you for this advice: I'll definitely remove the `const`!

FA


Re: Mixin Templates and Operators

2022-04-06 Thread Adam D Ruppe via Digitalmars-d-learn
On Wednesday, 6 April 2022 at 17:33:28 UTC, Steven Schveighoffer 
wrote:
As I mentioned elsewhere, it does work. But the situation I 
think must be that it's only one mixin template. Probably also 
you can't have any overloads in the type itself.


ooh yeah there's multiple here so the names don't 
overload and one on the time itself would override the ones from 
mixin template.


You'd have to alias them together on the type.


Re: Mixin Templates and Operators

2022-04-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/6/22 12:52 PM, Adam D Ruppe wrote:

On Wednesday, 6 April 2022 at 10:36:04 UTC, francesco.andreetto wrote:
Am I doing something wrong or it is impossible to use mixin templates 
like that?


mixin templates can't bring in operator overloads. The spec doesn't 
really say this I think, but that's the way it has been for a long time.


It only checks for operator overloads on the direct thing itself, no 
UFCS, no mixin template.


As I mentioned elsewhere, it does work. But the situation I think must 
be that it's only one mixin template. Probably also you can't have any 
overloads in the type itself.


Note that I also think string mixins would work perfectly fine. And UFCS 
will never work for operator overloads, but that is by design.


-Steve


Re: Mixin Templates and Operators

2022-04-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/6/22 6:36 AM, francesco.andreetto wrote:
I have two structs, point and vec, in which I want to implement some 
arithmetic operations.

The operations are:

```
point - point = vec
point + vec = point
```

Using mixin templates the code compiles but calling the operations in 
the main causes an "incompatible type" Error:


This seems like a bug in the compiler. You can mixin operator overloads 
using one mixin template, but not multiple.


e.g. raylib-d uses this:

https://github.com/schveiguy/raylib-d/blob/89733bab9fd1d3588c14f4aa54b62ad45022a105/source/raymathext.d#L75



I tried to implement a single template:

```d
mixin template sumDiff(T, R){
    R opBinary(string op)(T rhs) const
    if (op == "+" || op == "-"){
   return mixin("R(x " ~ op ~ " rhs.x, y " ~ op ~ "rhs.y, z " ~ op ~ 
" rhs.z)");

    }
}
```

but the same error occurs.


This is different from your original. If I do this, it works:

```d
mixin template both(T, R) {
   R opBinary(string op : "+")(T rhs) const
   {
  return R(x + rhs.x, y + rhs.y, z + rhs.z);
   }

   T opBinary(string op : "-")(R rhs) const
   {
  return T(x - rhs.x, y - rhs.y, z - rhs.z);
   }
}

struct point{
   float x, y, z;
   mixin both!(vec, point);
}
```


If I don't use the mixin templates and, instead, I overload the 
operations into the structures everything works.


It also works to call `opBinary` directly:

```d
vec v1 = p1.opBinary!"-"(p2);
```

Which leads me to believe it's not an ambiguity error, but rather just a 
straight omission on how the operator overloading works.


I think you should file a bug.

-Steve


Re: Mixin Templates and Operators

2022-04-06 Thread Adam D Ruppe via Digitalmars-d-learn
On Wednesday, 6 April 2022 at 10:36:04 UTC, francesco.andreetto 
wrote:
Am I doing something wrong or it is impossible to use mixin 
templates like that?


mixin templates can't bring in operator overloads. The spec 
doesn't really say this I think, but that's the way it has been 
for a long time.


It only checks for operator overloads on the direct thing itself, 
no UFCS, no mixin template.


Re: Mixin Templates and Operators

2022-04-06 Thread Tejas via Digitalmars-d-learn
On Wednesday, 6 April 2022 at 10:36:04 UTC, francesco.andreetto 
wrote:
I have two structs, point and vec, in which I want to implement 
some arithmetic operations.

The operations are:

```
point - point = vec
point + vec = point
```

Using mixin templates the code compiles but calling the 
operations in the main causes an "incompatible type" Error:


```d
mixin template sum(T, R) {
   R opBinary(string op)(T rhs) const
   if (op == "+"){
  return R(x + rhs.x, y + rhs.y, z + rhs.z);
   }
}

mixin template diff(T, R) {
   R opBinary(string op)(T rhs) const
   if (op == "-") {
  return R(x - rhs.x, y - rhs.y, z - rhs.z);
   }
}

struct point{
   float x, y, z;
   mixin diff!(point, vec);
   mixin sum!(vec, point);
}

struct vec{
   float x, y, z;
}

void main(){
   point p1 = {1,2,3}, p2 = {5,6,7};
   vec v1 = p1-p2;

   vec v2 = {2,-1,0};
   point p3 = p1+v2;
}
```
The output of `dub run` is

```
Performing "debug" build using /usr/bin/dmd for x86_64.
query ~master: building configuration "application"...
source/app.d(27,13): Error: incompatible types for `(p1) - 
(p2)`: both operands are of type `point`
source/app.d(30,15): Error: incompatible types for `(p1) + 
(v2)`: `point` and `vec`

/usr/bin/dmd failed with exit code 1.
```

I tried to implement a single template:

```d
mixin template sumDiff(T, R){
   R opBinary(string op)(T rhs) const
   if (op == "+" || op == "-"){
  return mixin("R(x " ~ op ~ " rhs.x, y " ~ op ~ "rhs.y, z 
" ~ op ~ " rhs.z)");

   }
}
```

but the same error occurs.

If I don't use the mixin templates and, instead, I overload the 
operations into the structures everything works.


```d
struct point{
   float x, y, z;

   vec opBinary(string op)(point rhs) const
   if (op == "-") {
  return vec(x - rhs.x, y - rhs.y, z - rhs.z);
   }

   point opBinary(string op)(vec rhs) const
   if (op == "+") {
  return point(x + rhs.x, y + rhs.y, z + rhs.z);
   }
}

struct vec{
   float x, y, z;
}

void main(){
   point p1 = {1,2,3}, p2 = {5,6,7};
   vec v1 = p1-p2;

   vec v2 = {2,-1,0};
   point p3 = p1+v2;
}
```

Am I doing something wrong or it is impossible to use mixin 
templates like that?


Looks like a compiler bug, since substituting the real methods 
makes the `mixin template` code compile fine


Also, remove the `const`, otherwise the method will word only on 
`const` instances even if the bug gets fixed


```d
mixin template sum(T, R) {
   R opBinary(string op)(T rhs) const
   if (op == "+"){
  return R(x + rhs.x, y + rhs.y, z + rhs.z);
   }
}

mixin template diff(T, R) {
   R opBinary(string op)(T rhs) const
   if (op == "-") {
  return R(x - rhs.x, y - rhs.y, z - rhs.z);
   }
}

struct point{
   float x, y, z;
   mixin diff!(point, vec);
   mixin sum!(vec, point);
}

struct vec{
   float x, y, z;
}

void main(){
   point p1 = {1,2,3}, p2 = {5,6,7};
   vec v1 = p1.opBinary!"-"(p2);   // made - explicit

   vec v2 = {2,-1,0};
   point p3 = p1.opBinary!"+"(v2);  // made + explicit
}


Mixin Templates and Operators

2022-04-06 Thread francesco.andreetto via Digitalmars-d-learn
I have two structs, point and vec, in which I want to implement 
some arithmetic operations.

The operations are:

```
point - point = vec
point + vec = point
```

Using mixin templates the code compiles but calling the 
operations in the main causes an "incompatible type" Error:


```d
mixin template sum(T, R) {
   R opBinary(string op)(T rhs) const
   if (op == "+"){
  return R(x + rhs.x, y + rhs.y, z + rhs.z);
   }
}

mixin template diff(T, R) {
   R opBinary(string op)(T rhs) const
   if (op == "-") {
  return R(x - rhs.x, y - rhs.y, z - rhs.z);
   }
}

struct point{
   float x, y, z;
   mixin diff!(point, vec);
   mixin sum!(vec, point);
}

struct vec{
   float x, y, z;
}

void main(){
   point p1 = {1,2,3}, p2 = {5,6,7};
   vec v1 = p1-p2;

   vec v2 = {2,-1,0};
   point p3 = p1+v2;
}
```
The output of `dub run` is

```
Performing "debug" build using /usr/bin/dmd for x86_64.
query ~master: building configuration "application"...
source/app.d(27,13): Error: incompatible types for `(p1) - (p2)`: 
both operands are of type `point`
source/app.d(30,15): Error: incompatible types for `(p1) + (v2)`: 
`point` and `vec`

/usr/bin/dmd failed with exit code 1.
```

I tried to implement a single template:

```d
mixin template sumDiff(T, R){
   R opBinary(string op)(T rhs) const
   if (op == "+" || op == "-"){
  return mixin("R(x " ~ op ~ " rhs.x, y " ~ op ~ "rhs.y, z " 
~ op ~ " rhs.z)");

   }
}
```

but the same error occurs.

If I don't use the mixin templates and, instead, I overload the 
operations into the structures everything works.


```d
struct point{
   float x, y, z;

   vec opBinary(string op)(point rhs) const
   if (op == "-") {
  return vec(x - rhs.x, y - rhs.y, z - rhs.z);
   }

   point opBinary(string op)(vec rhs) const
   if (op == "+") {
  return point(x + rhs.x, y + rhs.y, z + rhs.z);
   }
}

struct vec{
   float x, y, z;
}

void main(){
   point p1 = {1,2,3}, p2 = {5,6,7};
   vec v1 = p1-p2;

   vec v2 = {2,-1,0};
   point p3 = p1+v2;
}
```

Am I doing something wrong or it is impossible to use mixin 
templates like that?


Re: Which operators cannot be overloaded and why not?

2021-09-14 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Sep 13, 2021 at 06:19:20PM +, NonNull via Digitalmars-d-learn wrote:
> On Monday, 13 September 2021 at 16:12:34 UTC, H. S. Teoh wrote:
> > On Mon, Sep 13, 2021 at 02:12:36PM +, NonNull via
> > Digitalmars-d-learn wrote:
> > > Which operators cannot be overloaded and why not?
> > 
> > Others have already given the list, so I won't repeat that.
> 
> I didn't see unary &. Maybe others are missing.
[...]

IIRC, unary & cannot be overloaded for the same reasons &&, ||, and !
cannot be overloaded: it leads to hard-to-understand, hard-to-maintain
code.  Incidentally, C++ *does* allow overloading of &, ostensibly
because some wrapper types might want to use it to become transparent.
But one of the consequences of this is that now you need a
std::address-of pseudo-operator that *actually* takes an address of
something when you *really* mean to take the address of the wrapper
object instead of the wrapped object.  So & loses its original meaning
and has to be replaced by a std:: hack.  Which, to me, is abundant proof
that overloading & was a bad idea in the first place.

//

BTW, as an aside, as a example of why every-man-for-himself,
wild-wild-west operator overloading in C++ is a bad idea, consider these
two lines of C++ code:

fun(a, b);
gun(a, b);

What do they mean?  Ostensibly, these are function calls to two template
functions, specifying explicit template arguments.  Unfortunately, that
is not the case: only *one* of these lines is a template function call,
the other is something else altogether.  But nobody can tell the
difference unless they read the entire context, as shown below.
(Incidentally, this example also shows why C++'s choice of template
syntax was a poor one.) Compile and run with a C++ compiler to find out
what the actual behaviour is.


---
// Totally evil example of why C++ template syntax and free-for-all
// operator overloading is a Bad, Bad Idea.
#include 

struct Bad { };
struct B { };
struct A {
Bad operator,(B b) { return Bad(); }
};
struct D { };
struct Ugly {
D operator>(Bad b) { return D(); }
} U;
struct Terrible { } T;
struct Evil {
~Evil() {
std::cout << "Hard drive reformatted." << std::endl;
}
};
struct Nasty {
Evil operator,(D d) { return Evil(); }
};
struct Idea {
void operator()(A a, B b) {
std::cout << "Good idea, data saved." << std::endl;
}
Nasty operator<(Terrible t) { return Nasty(); }
} gun;

template
void fun(A a, B b) {
std::cout << "Have fun!" << std::endl;
}

int main() {
A a;
B b;

// What do these lines do?
fun(a, b);
gun(a, b);
}
---


T

-- 
Your inconsistency is the only consistent thing about you! -- KD


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread NonNull via Digitalmars-d-learn

On Monday, 13 September 2021 at 16:12:34 UTC, H. S. Teoh wrote:
On Mon, Sep 13, 2021 at 02:12:36PM +, NonNull via 
Digitalmars-d-learn wrote:

Which operators cannot be overloaded and why not?


Others have already given the list, so I won't repeat that.


I didn't see unary &. Maybe others are missing.


As to the "why":

In general, D tries to avoid the wild wild west, every operator 
for himself situation in C++ that leads to unreadable, 
unmaintainable code.


Thanks for this explanation. The consolidation you mention is 
great!





Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread user1234 via Digitalmars-d-learn

On Monday, 13 September 2021 at 18:06:42 UTC, NonNull wrote:

On Monday, 13 September 2021 at 14:42:42 UTC, jfondren wrote:

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

- condition al expression ` cond ? exp : exp `


And many other boolean operators, unary !, binary && and ||

https://dlang.org/spec/operatoroverloading.html lists all the 
overloadable operators, and 
https://dlang.org/spec/expression.html has all the operators, 
so "which operators" is a matter of close comparison.


Is there no list of such in an article online? It would be good 
if that work was done for once and for all, with a short 
explanation in each case, possibly with discussion in some 
cases of how to achieve results by other means.


well this whole thread is certainly the raw material for an 
article (or D blog post) on D operator overloads. Just, someone 
has to compile the informations and write the said article.


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread NonNull via Digitalmars-d-learn

On Monday, 13 September 2021 at 14:42:42 UTC, jfondren wrote:

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

- condition al expression ` cond ? exp : exp `


And many other boolean operators, unary !, binary && and ||

https://dlang.org/spec/operatoroverloading.html lists all the 
overloadable operators, and 
https://dlang.org/spec/expression.html has all the operators, 
so "which operators" is a matter of close comparison.


Is there no list of such in an article online? It would be good 
if that work was done for once and for all, with a short 
explanation in each case, possibly with discussion in some cases 
of how to achieve results by other means.




Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Sep 13, 2021 at 02:12:36PM +, NonNull via Digitalmars-d-learn wrote:
> Which operators cannot be overloaded and why not?

Others have already given the list, so I won't repeat that. As to the
"why":

In general, D tries to avoid the wild wild west, every operator for
himself situation in C++ that leads to unreadable, unmaintainable code.

For example, C++ allows you to separately overload <, <=, ==, >, >=, !=.
That means the programmer is free to define == and != in a way
completely inconsistent with each other, for example.  D solves this by
combining == and != into a single operator overload, opEquals, where !=
is the negation of ==. This ensures == and != are always consistent with
each other.  Same with <, <=, >, >=: C++ lets you overload each one
separately, potentially in a completely inconsistent way with each
other, so that somebody reading your code has no idea whether x < y
implies y >= x, or whether x < y implies y > x. Again, unreadable code.
D solves this by combining all these operators into a single overload:
opCmp.  This ensures consistency between all of these relative
comparison operators.

Similarly, prefix ++/-- and postfix ++/-- cannot be separately
overloaded; they are combined into a single overload, where postfix
++/--, as in `x++`, is simply rewritten by the compiler to the
equivalent of:

(){ auto tmp = x; x++; return tmp; }()

(Of course, this is just to illustrate the semantics. The compiler
doesn't actually create a lambda here.)

This ensures that prefix and postfix operators behave in the expected
way, so that ++x and x++ don't behave in two wildly different, unrelated
ways, like it sometimes happens in C++ code because C++ lets you define
separate overloads for them.

Combining these operator overloads have the additional benefit that less
overloads are needed to implement a numerical type: instead of needing
to separately implement ==, !=, <, <=, >, >=, you only have to implement
two overloads, opEquals and opCmp, and the compiler takes care of the
rest. Similarly, ++ and -- only need to be implement once each, and
you'll get the postfix varieties for free.

Furthermore, the boolean operators !, &&, || are not directly
overloadable. Again, C++ lets you separately overload them, which
guarantees that when you see (what looks like) a boolean expression in
C++, you have no idea what its true semantics are, because && could mean
something completely different from the usual meaning.  D doesn't let
you overload these operators, thereby ensuring that a boolean expression
remains a boolean expression: !, &&, || always have the standard
semantics.  What D *does* let you do is to define opCast!bool yourself,
so that you can define how a user-defined type converts to a bool, which
can then participate in the !, &&, || operators in the usual way.


In general, the philosophy in D is that operator overloading really
should be reserved for number-like (or math-like) objects, and
overloaded operators are expected to behave more-or-less like their
standard, non-overloaded meanings. Operator overloading of the variety
that C++ likes to do, like iostream's <<, >> overloads, are frowned
upon, because they obscure the surface meaning of the code and make it
hard to understand and maintain. (Incidentally, D *does* allow you to
overload '<<' and '>>'. It's just frowned upon to overload them in a way
that doesn't in someway represent bit-shifting.)  Furthermore,
overloaded operators are expected to behave analogously w.r.t. each
other, e.g., == and != should behave like opposites of each other; <
should not have completely unrelated semantics to >, and so on.


T

-- 
The right half of the brain controls the left half of the body. This means that 
only left-handed people are in their right mind. -- Manoj Srivastava


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread user1234 via Digitalmars-d-learn

On Monday, 13 September 2021 at 14:59:38 UTC, Paul Backus wrote:

On Monday, 13 September 2021 at 14:42:42 UTC, jfondren wrote:

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

- condition al expression ` cond ? exp : exp `


And many other boolean operators, unary !, binary && and ||

https://dlang.org/spec/operatoroverloading.html lists all the 
overloadable operators, and 
https://dlang.org/spec/expression.html has all the operators, 
so "which operators" is a matter of close comparison. "why 
not" is much harder to answer.


I think the intent is for the boolean operators to be handled 
via `opCast!bool`.


I didn't see it was already suggested and answered the same... 
but yet that's exactly the case.


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread user1234 via Digitalmars-d-learn

On Monday, 13 September 2021 at 15:29:05 UTC, user1234 wrote:

[...]
so this is a bit like the postincr case.


i.e "prevent the semantics to be hijacked".


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread user1234 via Digitalmars-d-learn

On Monday, 13 September 2021 at 14:42:42 UTC, jfondren wrote:

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

- condition al expression ` cond ? exp : exp `


And many other boolean operators, unary !, binary && and ||


They are all indirectly supported if `opCast` is overloaded:

```d
unittest
{
struct S
{
bool opCast(T = bool)(){return true;}
}
S s;
assert(s && s);
}
```

so this is a bit like the postincr case.




Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread Basile B. via Digitalmars-d-learn

On Monday, 13 September 2021 at 14:42:42 UTC, jfondren wrote:

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

- condition al expression ` cond ? exp : exp `


And many other boolean operators, unary !, binary && and ||

https://dlang.org/spec/operatoroverloading.html lists all the 
overloadable operators, and 
https://dlang.org/spec/expression.html has all the operators, 
so "which operators" is a matter of close comparison. "why not" 
is much harder to answer.


Oh! I have never noticed that `&&` and `||`, despite of being 
quite "ordinary" binary ops are not overloadable.


In 
[styx](https://styx-lang.gitlab.io/styx/attribute.html#operatorattribute) that works because, although inspired by the D way, in the sense that overloads are implemented in custom types, the selection is done using an expression template


```d
struct S {
@operator(a && b) function andAnd(T other): auto {return 
false}

}
```

So as long as the expression in the attribute argument looks like 
a valid expression the stuff is found (and the supprot code in 
the compiler is super simple), e.g with code in a body:


```d
e1 && e2; // look if e1 is an aggregate and if it contains 
@operator(a && b)
e1 + e2;  // look if e1 is an aggregate and if it contains 
@operator(a && b)

```

While D uses specific identifier + templates value param for 
strings.

(note that only the equivalent of D opBinary**Right** works...)

anyway. zorry for this off-topic.


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/13/21 10:47 AM, user1234 wrote:

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

what else ?


when you have

```d
alias AA1 = int[int];
alias AA2 = AA1[int];
```

then you can write

```d
AA2 aa;
aa[0] = [0 : 0];
aa[0][0] = 0;
```

The `[0][0]` cannot be expressed using operator overloads (and a custom 
map type that implements opIndexAssign).But this case is rather due to 
the fact that druntime seems to do something a bit unusal here 
(according to an old discussion that happend once on irc).




This is because the compiler calls a different hook depending on the 
usage of the expression `aa[0]`. Which one it calls is not consistent.


There isn't an analog for indexing overloads.

A further example:

```d
int[int] aa;
aa[0]++; // ok
void foo(ref int x) {x++;}
foo(aa[1]); // range violation
```

-Steve


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread Paul Backus via Digitalmars-d-learn

On Monday, 13 September 2021 at 14:42:42 UTC, jfondren wrote:

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

- condition al expression ` cond ? exp : exp `


And many other boolean operators, unary !, binary && and ||

https://dlang.org/spec/operatoroverloading.html lists all the 
overloadable operators, and 
https://dlang.org/spec/expression.html has all the operators, 
so "which operators" is a matter of close comparison. "why not" 
is much harder to answer.


I think the intent is for the boolean operators to be handled via 
`opCast!bool`.


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread user1234 via Digitalmars-d-learn

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

what else ?


when you have

```d
alias AA1 = int[int];
alias AA2 = AA1[int];
```

then you can write

```d
AA2 aa;
aa[0] = [0 : 0];
aa[0][0] = 0;
```

The `[0][0]` cannot be expressed using operator overloads (and a 
custom map type that implements opIndexAssign).But this case is 
rather due to the fact that druntime seems to do something a bit 
unusal here (according to an old discussion that happend once on 
irc).




Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread jfondren via Digitalmars-d-learn

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

- condition al expression ` cond ? exp : exp `


And many other boolean operators, unary !, binary && and ||

https://dlang.org/spec/operatoroverloading.html lists all the 
overloadable operators, and 
https://dlang.org/spec/expression.html has all the operators, so 
"which operators" is a matter of close comparison. "why not" is 
much harder to answer.


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread user1234 via Digitalmars-d-learn

On Monday, 13 September 2021 at 14:12:36 UTC, NonNull wrote:

Which operators cannot be overloaded and why not?


Let's start the list.

- `new` and `delete`

Because operators are overloaded in aggregates
new was supported but not anymore, the idea is
that a an aggregate should not be tied a specific allocator.

- post incr/decr

See 
[https://dlang.org/spec/operatoroverloading.html#postincrement_postdecrement_operators](explantations). This is an arbitrary limitation imho but the current way enfore that the side effect is not apllied to the expression result.


- condition al expression ` cond ? exp : exp `

No idea why it is not supported... nobody has never complained 
tho ;)


- `typeid`

Same... the result of typeid has to be a TypeInfoClass, so 
there's not much to do... exactness is expected


- `is` (identity)

could be but I suppose that this stuff needs to be correct to 
keep code consistent


what else ?


Which operators cannot be overloaded and why not?

2021-09-13 Thread NonNull via Digitalmars-d-learn

Which operators cannot be overloaded and why not?



Re: Not allowed to globally overload operators?

2021-07-20 Thread Tejas via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 18:32:26 UTC, Ali Çehreli wrote:

On 7/19/21 11:20 PM, Tejas wrote:

> trying to create the spaceship operator of C++

Just to make sure, D's opCmp returns an int. That new C++ 
operator was added to provide the same semantics.


Ali


I know. As I already mentioned,  I just wanted the ```<=>``` 
symbol :(


Re: Not allowed to globally overload operators?

2021-07-20 Thread Ali Çehreli via Digitalmars-d-learn

On 7/20/21 11:49 AM, H. S. Teoh wrote:

> On Tue, Jul 20, 2021 at 11:32:26AM -0700, Ali Çehreli via 
Digitalmars-d-learn wrote:

>> On 7/19/21 11:20 PM, Tejas wrote:
>>
>>> trying to create the spaceship operator of C++
>>
>> Just to make sure, D's opCmp returns an int. That new C++ operator was
>> added to provide the same semantics.
> [...]
>
> FYI, opCmp *may* return float, which may be useful sometimes for
> implementing partial orders (return float.nan when two elements are
> incomparable).

Thanks. For that matter, opCmp can return a UDT (and bool as well as 
demonstarted below) but then the UDT cannot know what to do in its opCmp: :)


import std.stdio;

void main() {
  S a, b;
  auto result = a < b;
  // The operator above is reduced to the following:
  //
  //   a.opCmp(b) < 0;
  //
  // (It would be 'a.opCmp(b) >= 0' if we used the >= operator, etc.)
  //
  // But because the result of opCmp is an O object in this code
  // (let's call it 'o'), the reduction is applied to 'o < 0' as well:
  //
  //   o.opCmp(0);
  //
  // where, O.opCmp will receive a 0 'int' value but will never know
  // operator context we are in. (<, >=, etc.)
}

struct S {
  // Weirdly returns an O.
  O opCmp(const S that) {
return O();
  }
}

struct O {
  bool opCmp(int result) {
// result will always be '0' in the case of reduction because it
// will be the 0 used in code reduction by dmd.

// We might be able to do something here but we don't know the
// operator context. Are we inside <, >=, etc?

// Extra credit: This is similar to being able to return float.nan
// but I can't decipher the semantics at this time. :)
return true;
  }
}

Ali




Re: Not allowed to globally overload operators?

2021-07-20 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 18:49:07 UTC, H. S. Teoh wrote:
On Tue, Jul 20, 2021 at 11:32:26AM -0700, Ali Çehreli via 
Digitalmars-d-learn wrote:

On 7/19/21 11:20 PM, Tejas wrote:

> trying to create the spaceship operator of C++

Just to make sure, D's opCmp returns an int. That new C++ 
operator was added to provide the same semantics.

[...]

FYI, opCmp *may* return float, which may be useful sometimes 
for implementing partial orders (return float.nan when two 
elements are incomparable).


To be precise about it: `opCmp` must return a value that can be 
compared with `0` using `<` and `>`. Any integer or 
floating-point type will satisfy this requirement.


Re: Not allowed to globally overload operators?

2021-07-20 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jul 20, 2021 at 11:32:26AM -0700, Ali Çehreli via Digitalmars-d-learn 
wrote:
> On 7/19/21 11:20 PM, Tejas wrote:
> 
> > trying to create the spaceship operator of C++
> 
> Just to make sure, D's opCmp returns an int. That new C++ operator was
> added to provide the same semantics.
[...]

FYI, opCmp *may* return float, which may be useful sometimes for
implementing partial orders (return float.nan when two elements are
incomparable).


T

-- 
"Outlook not so good." That magic 8-ball knows everything! I'll ask about 
Exchange Server next. -- (Stolen from the net)


Re: Not allowed to globally overload operators?

2021-07-20 Thread Ali Çehreli via Digitalmars-d-learn

On 7/19/21 11:20 PM, Tejas wrote:

> trying to create the spaceship operator of C++

Just to make sure, D's opCmp returns an int. That new C++ operator was 
added to provide the same semantics.


Ali



Re: Not allowed to globally overload operators?

2021-07-20 Thread Tejas via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 06:34:45 UTC, vit wrote:

On Tuesday, 20 July 2021 at 06:20:34 UTC, Tejas wrote:

...
Initially, I was trying to create the spaceship operator of 
C++, but we aren't allowed to create new operators

...


D has spaceship operator: opCmp 
(https://dlang.org/spec/operatoroverloading.html#compare).


I know, but I just really wanted the ```<=>```  :(


Re: Not allowed to globally overload operators?

2021-07-20 Thread Tejas via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 06:30:56 UTC, Mike Parker wrote:

On Tuesday, 20 July 2021 at 06:20:34 UTC, Tejas wrote:

Why isn't it working by default?

Initially, I was trying to create the spaceship operator of 
C++, but we aren't allowed to create new operators, it seems. 
Then I just wanted to verify whether we can even overload an 
operator globally, but even that seems to be failing, atleast 
for me.


From the docs:

Operator overloading is accomplished by rewriting operators 
whose operands are class or struct objects into calls to 
specially named members.


https://dlang.org/spec/operatoroverloading.html

Note the word "members".



Ack. I remember reading the spec but have forgotten that detail 
multiple times now.

See also:

https://dlang.org/articles/rationale.html#why-no-global-operator-functions


Well, this is new. **sigh** Guess I'll have to find another way 
to implement spaceship then. I don't disagree with the rationale, 
but it is a little inconvenient in my case.


Re: Not allowed to globally overload operators?

2021-07-20 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 06:20:34 UTC, Tejas wrote:

Why isn't it working by default?

Initially, I was trying to create the spaceship operator of 
C++, but we aren't allowed to create new operators, it seems. 
Then I just wanted to verify whether we can even overload an 
operator globally, but even that seems to be failing, atleast 
for me.


From the docs:

Operator overloading is accomplished by rewriting operators 
whose operands are class or struct objects into calls to 
specially named members.


https://dlang.org/spec/operatoroverloading.html

Note the word "members".

See also:

https://dlang.org/articles/rationale.html#why-no-global-operator-functions



Re: Not allowed to globally overload operators?

2021-07-20 Thread vit via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 06:20:34 UTC, Tejas wrote:

...
Initially, I was trying to create the spaceship operator of 
C++, but we aren't allowed to create new operators

...


D has spaceship operator: opCmp 
(https://dlang.org/spec/operatoroverloading.html#compare).





Not allowed to globally overload operators?

2021-07-20 Thread Tejas via Digitalmars-d-learn

The following doesn't work:
```d
import std;
int opBinary(string s:"+")(int a, int b){
int result;
ab? (result = 1): (result = 0);
return result;
}
void main(){
int f = 1 + 5;
writeln(f);
}
```
It outputs 6

But if I manually write it as
```d
int f = opBinary!"+"(1,5);
```
It works as expected.

Why isn't it working by default?

Initially, I was trying to create the spaceship operator of C++, 
but we aren't allowed to create new operators, it seems. Then I 
just wanted to verify whether we can even overload an operator 
globally, but even that seems to be failing, atleast for me.


[Issue 2450] Error using operators from named template mixin

2021-05-29 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=2450

--- Comment #4 from Dlang Bot  ---
dlang/dmd pull request #12600 "merge stable" was merged into master:

- 79a6f7cf9d604eea33b072a9ab30170daeeda696 by Boris Carvajal:
  Fix Issue 2450 - Error using operators from named template mixin (version 2)

https://github.com/dlang/dmd/pull/12600

--


[Issue 2450] Error using operators from named template mixin

2021-05-20 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=2450

--- Comment #3 from Dlang Bot  ---
dlang/dmd pull request #12542 "Fix Issue 2450 - Error using operators from
named template mixin (version 2)" was merged into stable:

- b071e9d04e8db0612d6c3350a6383d7e1ae0eecc by Boris Carvajal:
  Fix Issue 2450 - Error using operators from named template mixin (version 2)

https://github.com/dlang/dmd/pull/12542

--


[Issue 21758] std.experimental.checkedint opBinaryRight with integer left-hand side does not compile for any operators except + and -

2021-04-27 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=21758

--- Comment #4 from Dlang Bot  ---
dlang/phobos pull request #8012 "merge stable" was merged into master:

- e516ec9351c9897417805a9f2b0839c9c099a97e by Nathan Sashihara:
  Fix Issue 21758 - std.experimental.checkedint opBinaryRight with integer
left-hand side does not compile for any operators except + and -

https://github.com/dlang/phobos/pull/8012

--


[Issue 21758] std.experimental.checkedint opBinaryRight with integer left-hand side does not compile for any operators except + and -

2021-04-25 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=21758

--- Comment #3 from Dlang Bot  ---
dlang/phobos pull request #7964 "merge stable" was merged into master:

- 6f430a7202366c1699618c7fe70f7d7800c7effe by Nathan Sashihara:
  Fix Issue 21758 - std.experimental.checkedint opBinaryRight with integer
left-hand side does not compile for any operators except + and -

https://github.com/dlang/phobos/pull/7964

--


Re: How to allow +=, -=, etc operators and keep encapsulation?

2021-04-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/12/21 2:16 PM, Jack wrote:

Give this class:

```d
class A
{
 int X() { return x; }
 int X(int v) { return x = v;}

 private int x;
}
```

I'd like to allow use ```+=```, ```-=``` operators on ```X()``` and keep 
encapsulation. What's a somehow elegant way to do that?


It's really hard to do.

One problem is lifetime management. There is no way to do something like 
`ref`, which does not provide a way to make a copy of the original thing 
(the reference) in @safe code.


But the way I'd tackle it is to write a pseudo-reference wrapper that 
forwards to the getter/setter.


I'm sure there's a mixin template solution that works, I just don't have 
the time to code it out right now.


You can take a look at Mike Franklin's unpublished DIP here for inspiration:
* [DIP conversation](https://github.com/dlang/DIPs/pull/97)
* [DIP 
text](https://github.com/dlang/DIPs/blob/fdd016a16bf1898fda901b9d716f5bcc6021c1a7/DIPs/DIP1xxx-mvf.md)


-Steve


Re: How to allow +=, -=, etc operators and keep encapsulation?

2021-04-12 Thread evilrat via Digitalmars-d-learn

On Monday, 12 April 2021 at 18:16:14 UTC, Jack wrote:

Give this class:

```d
class A
{
int X() { return x; }
int X(int v) { return x = v;}

private int x;
}
```

I'd like to allow use ```+=```, ```-=``` operators on ```X()``` 
and keep encapsulation. What's a somehow elegant way to do that?


I assume you know what you are doing, right?
In this specific case I would say you can probably stick with it 
as is since you can have value checks in getter/setter, you can 
validate and correct values before it mess up the internal state, 
and calculate X without exposing internal state (today it may be 
int x, tomorrow you change it to be stored as string, who 
knows...).


But this example doesn't really tell if it's acceptable in what 
you are trying to achieve.


Otherwise:

What you need is called abstraction, you provide high level 
interface to your problem without exposing internal state which 
is implementation detail, which gives you freedom to modify 
internal logic without breaking everyone's code that consume your 
interface.


Assuming A is some special scalar type you just implement all 
operations in a way that makes it only relevant as a whole. 
Otherwise if you still need to peek on its private members you 
have leaky abstractions (it is called feature envy).




How to allow +=, -=, etc operators and keep encapsulation?

2021-04-12 Thread Jack via Digitalmars-d-learn

Give this class:

```d
class A
{
int X() { return x; }
int X(int v) { return x = v;}

private int x;
}
```

I'd like to allow use ```+=```, ```-=``` operators on ```X()``` 
and keep encapsulation. What's a somehow elegant way to do that?


[Issue 21758] std.experimental.checkedint opBinaryRight with integer left-hand side does not compile for any operators except + and -

2021-03-24 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=21758

Dlang Bot  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |FIXED

--- Comment #2 from Dlang Bot  ---
dlang/phobos pull request #7908 "std.experimental.checkedint opBinaryRight with
integer left-hand side does not compile for any operators except + and -" was
merged into stable:

- 9dc134c8db1f9a547552e471d9b5a5009a6b64b7 by Nathan Sashihara:
  Fix Issue 21758 - std.experimental.checkedint opBinaryRight with integer
left-hand side does not compile for any operators except + and -

https://github.com/dlang/phobos/pull/7908

--


[Issue 21758] std.experimental.checkedint opBinaryRight with integer left-hand side does not compile for any operators except + and -

2021-03-24 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=21758

Dlang Bot  changed:

   What|Removed |Added

   Keywords||pull

--- Comment #1 from Dlang Bot  ---
@n8sh created dlang/phobos pull request #7908 "std.experimental.checkedint
opBinaryRight with integer left-hand side does not compile for any operators
except + and -" fixing this issue:

- Fix Issue 21758 - std.experimental.checkedint opBinaryRight with integer
left-hand side does not compile for any operators except + and -

https://github.com/dlang/phobos/pull/7908

--


[Issue 21758] std.experimental.checkedint opBinaryRight with integer left-hand side does not compile for any operators except + and -

2021-03-24 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=21758

Nathan S.  changed:

   What|Removed |Added

Summary|std.experimental.checkedint |std.experimental.checkedint
   |opBinaryRight with integer  |opBinaryRight with integer
   |left-hand side does not |left-hand side does not
   |compile for any operations  |compile for any operators
   |except + and -  |except + and -

--


Re: Unary operators for Variants

2021-03-10 Thread Imperatorn via Digitalmars-d-learn

On Tuesday, 9 March 2021 at 20:05:07 UTC, Jeff wrote:
So, I can't seem to get unary operators to work with variants. 
For example:


Variant x = 10;
writeln(-x); // Error: x is not of arithmetic type, it is a 
VariantN!32LU


Obviously binary operators like + work fine. Is there a reason 
opUnary wasn't implemented as well? Is there a work-around for 
me to implement it myself outside of the VariantN class?


Thanks!


Try jsvar

https://dpldocs.info/experimental-docs/arsd.jsvar.html


Unary operators for Variants

2021-03-09 Thread Jeff via Digitalmars-d-learn
So, I can't seem to get unary operators to work with variants. 
For example:


Variant x = 10;
writeln(-x); // Error: x is not of arithmetic type, it is a 
VariantN!32LU


Obviously binary operators like + work fine. Is there a reason 
opUnary wasn't implemented as well? Is there a work-around for me 
to implement it myself outside of the VariantN class?


Thanks!


[Issue 21124] New: Multiple templated is expressions used with logical operators

2020-08-05 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=21124

  Issue ID: 21124
   Summary: Multiple templated is expressions used with logical
operators
   Product: D
   Version: D2
  Hardware: x86
OS: Linux
Status: NEW
  Severity: enhancement
  Priority: P1
 Component: dmd
  Assignee: nob...@puremagic.com
  Reporter: john.michael.h...@gmail.com

The code below fails to compile because the template parameter U is in both is
statements in isFoo. The code for isFoo2, which changes the U in the second is
statement, compiles without error. 

I see nothing in the specification that would suggest that isFoo should fail to
compile, though I may have missed it. Nevertheless, there is a workaround.

struct Foo(T)
{
T x;
}

struct Foo(T, U)
{
T x;
}

enum bool isFoo(T) = is(T : Foo!(U), U) || is(T : Foo!(U, V), U, V);
enum bool isFoo2(T) = is(T : Foo!(U), U) || is(T : Foo!(W, V), W, V);

void main()
{
static assert(isFoo!(Foo!(int)));
static assert(isFoo!(Foo!(int, int)));
static assert(isFoo2!(Foo!(int)));
static assert(isFoo2!(Foo!(int, int)));
}

--


Re: Overload comparison operators for "nullable" types

2020-08-01 Thread Oleg B via Digitalmars-d-learn

On Thursday, 30 July 2020 at 14:52:17 UTC, H. S. Teoh wrote:
On Thu, Jul 30, 2020 at 01:41:05PM +, Oleg B via 
Digitalmars-d-learn wrote: [...]
Logically we can compare versions, but what must return 
`opCmp` if one of versions has 'not comparible' state?

[...]

opCmp is allowed to return float; so you could return float.nan 
in this case.



T


Thank you! Simple answer but not in documentation...


Re: Overload comparison operators for "nullable" types

2020-07-30 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jul 30, 2020 at 01:41:05PM +, Oleg B via Digitalmars-d-learn wrote:
[...]
> Logically we can compare versions, but what must return `opCmp` if one of
> versions has 'not comparible' state?
[...]

opCmp is allowed to return float; so you could return float.nan in this
case.


T

-- 
"Real programmers can write assembly code in any language. :-)" -- Larry Wall


Overload comparison operators for "nullable" types

2020-07-30 Thread Oleg B via Digitalmars-d-learn

Hello!

For example we can imagine struct Version.
Version can be old or new and can be 'badly formed' or 
'undefined' or other 'not comparible' ('uncompatible') state.


Logically we can compare versions, but what must return `opCmp` 
if one of versions has 'not comparible' state?


I think strategy of throwing exception in `opCmp` is bad because 
some types can be 'not comparible' not because they is `null` or 
`undefined`, 'not comparible' can be two objects in some working 
states.


If we add `opEquals` we can check 'not comparible' and return 
`false`, but operators `a <= b` and `a >= b` not expands under 
the hood as `a < b || a == b`, they only call `opCmp` and if it 
returns 0 considered arguments are equals.


Rewrite `a <= b` as `a < b || a == b` is not intuitive and can 
get bugs if new user will use code (or old user forgot about 
this). Checking 'not comparible' state before `a <= b` is not 
intuitive too.


`opBinary` can't overload comparison.

We have same type of problem if wrap simple `double` into struct 
and try overload comparison (double.nan has own behavior).


Problem can be solved if we add new `opCmpEx` into language spec 
that return 4 states: more, less, equal, not equal.

Or if we allow `opBinary` overload comparisons.

May be I don't understand something important and this problem is 
not exists?


May be in cases where can be 'not comparible' state we should not 
use overload of comparison operators? But it looks like 
overloading conception isn't completed and can be improved.


Re: Is it possible to implement operators as ordinary functions?

2020-05-18 Thread data pulverizer via Digitalmars-d-learn

On Tuesday, 19 May 2020 at 02:42:22 UTC, Adam D. Ruppe wrote:

On Tuesday, 19 May 2020 at 02:36:24 UTC, data pulverizer wrote:
I was wandering if it possible to implement operators as 
ordinary functions instead of as member functions of a class 
or struct for example something like this:


nope, it must be done as member functions.


Thanks!


Re: Is it possible to implement operators as ordinary functions?

2020-05-18 Thread Adam D. Ruppe via Digitalmars-d-learn

On Tuesday, 19 May 2020 at 02:36:24 UTC, data pulverizer wrote:
I was wandering if it possible to implement operators as 
ordinary functions instead of as member functions of a class or 
struct for example something like this:


nope, it must be done as member functions.


Is it possible to implement operators as ordinary functions?

2020-05-18 Thread data pulverizer via Digitalmars-d-learn
I was wandering if it possible to implement operators as ordinary 
functions instead of as member functions of a class or struct for 
example something like this:


```
import std.stdio: writeln;

struct Int{
  int data = 0;
}

Int opBinary(string op)(Int x1, Int x2)
{
  static if((op == "+") || (op == "-") || (op == "*") || (op == 
"/"))

  {
int ret;
mixin("ret = x1.data " ~ op ~ " x2.data");
return ret;
  }else{
static assert(0, "Operator unknown.");
  }
}

void main()
{
  Int x = Int(1);
  Int y = Int(2);
  writeln("Output: ", x + y);
}

```


Compiler bug ? -preview=intpromote and Integral promotion rules not being followed for unary + - ~ operators

2020-05-14 Thread wjoe via Digitalmars-d-learn
I have a container which provides access to data via a handle. 
For book keeping I calculate some bitmasks.
Previously, when the handle type as well as the constants were 
uint, everything compiled fine.
Today I added a template parameter to be able to specify the 
handle type and I ran into this problem.


I've read the following information on the matter:

https://forum.dlang.org/thread/yqfhytyhivltamujd...@forum.dlang.org
https://issues.dlang.org/show_bug.cgi?id=18380
https://dlang.org/changelog/2.078.0.html#fix16997

However I still don't see the problem with regards to unsigned 
types.
Why is it necessary to promote a ushort or ubyte to int for the 
purpose of shifting or the one's complement ?
At least the code at the bottom of the post seems to produce 
correct results.


One problem I see with the bug fix is that, AFAIK, the int type 
in C is not a fixed bit type like it is in D where it is defined 
to be 32 bit and therefore casting to int in D can't really 
reproduce the C behavior. What  am I missing ?


Back to my container.
* Using a 32 bit type, i.e. uint, everything compiles fine.

* Using a 16 or 8 bit type, i.e. ushort and ubyte, the compiler 
complains with -preview=intpromote for the pragmas and errors out 
on assignments of the same types.

i.e. e.g.

alias handle_t = ushort;
enum handle_t MASK = 0x8000;
handle_t handle = ~MASK; // the error message is basically: 
[value is promoted to int and] 32769 can't be assigned to ushort


* Using a 64 bit type, i.e. ulong, the whole thing blows up 
because the compiler pro-, or rather, demotes the ulong to int 
and int << 40 is obviously violating a constraint of 0..31 for 
32bit types.


void main()
{
import std.conv: to;
import std.stdio;
alias t = ushort;
enum t m = 0x8000;
pragma (msg, m.to!string(16));
pragma (msg, (~m).to!string(16));
pragma (msg, (cast(int)m).to!string(16));
pragma (msg, (~cast(int)m).to!string(16));
}

2.063  : Success with output:
-
8000
7FFF
8000
7FFF
-

2.064   to 2.077.1: Success with output:
-
8000
7FFF
8000
7FFF
-

2.078.1 to 2.084.1: Success with output:
-
8000
onlineapp.d(8): Deprecation: integral promotion not done for 
`~cast(ushort)32768u`, use '-transition=intpromote' switch or 
`~cast(int)(cast(ushort)32768u)`

7FFF
8000
7FFF
-

Apart from the fact that I end up with an int, which causes all 
kinds of havoc and the annoyance that i need to cast a ushort to 
ushort to be able to assign it to a ushort, it appears to me that 
all the results are correct.


[Issue 11964] Poor diagnostic in static assert with boolean operators

2020-03-20 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=11964

Basile-z  changed:

   What|Removed |Added

 CC|b2.t...@gmx.com |

--


[Issue 11964] Poor diagnostic in static assert with boolean operators

2020-02-20 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=11964

Basile-z  changed:

   What|Removed |Added

   Keywords||diagnostic
 Status|NEW |RESOLVED
 CC||b2.t...@gmx.com
 Resolution|--- |WORKSFORME

--- Comment #3 from Basile-z  ---
The original expression is maintained now

Error: static assert:  `1 < 0 && (a < b) && (b < c)` is false

--


[Issue 1974] overloaded assignment operators work on non-lvalues

2019-10-24 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=1974

RazvanN  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |INVALID

--- Comment #2 from RazvanN  ---
Closing on the basis of:
https://forum.dlang.org/post/hyacdnjwraldlnmdl...@forum.dlang.org

--


[Issue 20210] version blocks with boolean operators

2019-09-16 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=20210

anonymous4  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |DUPLICATE

--- Comment #2 from anonymous4  ---
see workaround in issue 19495

*** This issue has been marked as a duplicate of issue 7417 ***

--


[Issue 2450] Error using operators from named template mixin

2019-09-14 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=2450

Dlang Bot  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |FIXED

--- Comment #2 from Dlang Bot  ---
dlang/dmd pull request #10406 "Fix Issue 2450 - Error using operators from
named template mixin" was merged into master:

- dd79b0cb45ef8686978f6b5896cb829af8120ff7 by RazvanN7:
  Fix Issue 2450 - Error using operators from named template mixin

https://github.com/dlang/dmd/pull/10406

--


[Issue 2450] Error using operators from named template mixin

2019-09-13 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=2450

Dlang Bot  changed:

   What|Removed |Added

   Keywords||pull

--- Comment #1 from Dlang Bot  ---
@RazvanN7 created dlang/dmd pull request #10406 "Fix Issue 2450 - Error using
operators from named template mixin" fixing this issue:

- Fix Issue 2450 - Error using operators from named template mixin

https://github.com/dlang/dmd/pull/10406

--


[Issue 20210] version blocks with boolean operators

2019-09-13 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=20210

--- Comment #1 from KnightMare  ---
this issue comes from 
https://issues.dlang.org/show_bug.cgi?id=20211
where I tried to determine probably existing version

"OT:" comes from issue:20211 too. 
then I decided to split issues.
so just ignore "OT:" in header

--


[Issue 20210] New: version blocks with boolean operators

2019-09-13 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=20210

  Issue ID: 20210
   Summary: version blocks with boolean operators
   Product: D
   Version: D2
  Hardware: All
OS: All
Status: NEW
  Severity: enhancement
  Priority: P1
 Component: dmd
  Assignee: nob...@puremagic.com
  Reporter: blac...@bk.ru

OT:
add to version check blocks some boolean operators
cuz next is more clear than indented monster at the bottom

version (Dip1000 || DIP1000 || dip1000) {
  pragma( msg, "D1000"); 
} else {
  pragma( msg, "no D1000"); 
}

// current state only supports && and !&&
version(A) version(B) { // replacement only for A && B
} else { /* !A || !B */ }

version (Dip1000) { 
pragma( msg, "D1000"); // same logic many times
} else {
version (DIP1000) {
pragma( msg, "D1000"); 
} else {
version (dip1000) {
pragma( msg, "D1000"); 
} else {
pragma( msg, "no D1000"); 
}
}
}

--


[Issue 1974] overloaded assignment operators work on non-lvalues

2019-09-13 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=1974

RazvanN  changed:

   What|Removed |Added

 CC||razvan.nitu1...@gmail.com

--- Comment #1 from RazvanN  ---
This is a bit problematic because there are 2 points of view on this:

1. From a high-level point of view, the bug report is valid, you are trying to
assign to an rvalue (x.test() = x.test() + 1337) which should an error.

2. From a lowering point of view you are basically calling the member function
of a temporary object (x.test.opAddAssign(1337)), which by the current rules is
valid behavior.

I guess that what could be implemented is something along the lines of: if the
opAssign/op*Assign function is pure, then you can error/warn because the call
has no effect, otherwise it is possible that the assign function has side
effects so calling it is correct. Anyhow, maybe I am over-engineering this?

--


Re: Do @property attributes not allow postincrement operators

2019-04-13 Thread Jamie via Digitalmars-d-learn

On Sunday, 14 April 2019 at 02:11:52 UTC, Mike Franklin wrote:

On Sunday, 14 April 2019 at 01:54:39 UTC, Jamie wrote:

Do @property attributes not allow postincrement operators?
...


It's a long standing issue (going on 7 years old)
...
I plan on getting to it, but there are other pressing things 
I'm trying to get out of the way.


Mike


Thanks Mike -- appears I didn't do a thorough enough search for 
this behaviour. Looking forward to it being implemented, cheers.


Re: Do @property attributes not allow postincrement operators

2019-04-13 Thread Mike Franklin via Digitalmars-d-learn

On Sunday, 14 April 2019 at 01:54:39 UTC, Jamie wrote:

Do @property attributes not allow postincrement operators?

import std.stdio;

struct Foo {
@property bar() { return 10; }
@property bar(int x) { writeln(x); }
}

void main()
{
Foo foo;
writeln(foo.bar); // actually calls foo.bar();
foo.bar = 10; // calls foo.bar(10);

// following doesn't work
foo.bar++; // would expect this to call foo.bar(foo.bar() + 
1);

// have to use:
foo.bar = foo.bar + 1;
writeln(foo.bar);
}


It's a long standing issue (going on 7 years old)

https://issues.dlang.org/show_bug.cgi?id=8006

There's an implementation at 
https://github.com/dlang/dmd/pull/7079


It requires a DIP, which you can find at 
https://github.com/dlang/DIPs/pull/97


However, in preparing that DIP other issues were discovered with 
@property, so we need to create a DIP to fix those issues first.


I plan on getting to it, but there are other pressing things I'm 
trying to get out of the way.


Mike


Do @property attributes not allow postincrement operators

2019-04-13 Thread Jamie via Digitalmars-d-learn

Do @property attributes not allow postincrement operators?

import std.stdio;

struct Foo {
@property bar() { return 10; }
@property bar(int x) { writeln(x); }
}

void main()
{
Foo foo;
writeln(foo.bar); // actually calls foo.bar();
foo.bar = 10; // calls foo.bar(10);

// following doesn't work
foo.bar++; // would expect this to call foo.bar(foo.bar() + 
1);

// have to use:
foo.bar = foo.bar + 1;
writeln(foo.bar);
}


[Issue 11500] Bringing mixed-in operators and constructors to the overload set

2019-03-10 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=11500

Basile-z  changed:

   What|Removed |Added

   See Also||https://issues.dlang.org/sh
   ||ow_bug.cgi?id=19729

--


[Issue 19200] Variant operators don't overload correctly

2018-09-02 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=19200

github-bugzi...@puremagic.com changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |FIXED

--


[Issue 19200] Variant operators don't overload correctly

2018-09-02 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=19200

--- Comment #1 from github-bugzi...@puremagic.com ---
Commits pushed to master at https://github.com/dlang/phobos

https://github.com/dlang/phobos/commit/71fc01cc63ee28648bdcd19faf8255c4dfeaf290
Fix issue 19200

https://github.com/dlang/phobos/commit/4873119553666819b4810a1318998eaad7476b08
Merge pull request #6684 from Biotronic/issue-19200

Fix issue 19200 - Variant operators don't overload correctly
merged-on-behalf-of: Petar Kirov 

--


[Issue 19200] New: Variant operators don't overload correctly

2018-08-28 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=19200

  Issue ID: 19200
   Summary: Variant operators don't overload correctly
   Product: D
   Version: D2
  Hardware: x86
OS: Windows
Status: NEW
  Severity: normal
  Priority: P1
 Component: phobos
  Assignee: nob...@puremagic.com
  Reporter: simen.kja...@gmail.com

There are issues when using Variant with types that have their own overloaded
operators:

struct S {
static int opBinaryRight(string op : "|", T)(T rhs) {
return 3;
}
}

unittest {
import std.variant;
S s;
Variant v;
auto b = v | s;
}

std\variant.d(1004): Error: no property min for type S

In addition, Variant's operator overloads are of the old kind (opAdd, opMul,
and so on). These should be updated anyway.

--


Re: Tired by deprecation message for unary operators on 8/16 bit vars ? A simple solution

2018-06-07 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 07, 2018 at 05:02:09PM +, Johan Engelen via Digitalmars-d wrote:
> On Thursday, 7 June 2018 at 15:18:49 UTC, H. S. Teoh wrote:
> > 
> > Now all you have to do is to add operator overloading to make the
> > wrapper type infectious, and a convenience function that can be
> > easily typed, and you get:
> 
> [...]
> 
> I'd like to have this in the stdlib, what are the chances?
[...]

Just copy-n-paste my code into your local Phobos repo and submit a PR.
;-)


T

-- 
Creativity is not an excuse for sloppiness.


Re: Tired by deprecation message for unary operators on 8/16 bit vars ? A simple solution

2018-06-07 Thread Johan Engelen via Digitalmars-d

On Thursday, 7 June 2018 at 15:18:49 UTC, H. S. Teoh wrote:


Now all you have to do is to add operator overloading to make 
the wrapper type infectious, and a convenience function that 
can be easily typed, and you get:


[...]

I'd like to have this in the stdlib, what are the chances?

-Johan



Re: Tired by deprecation message for unary operators on 8/16 bit vars ? A simple solution

2018-06-07 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 07, 2018 at 03:52:10PM +, Basile B. via Digitalmars-d wrote:
> On Thursday, 7 June 2018 at 15:18:49 UTC, H. S. Teoh wrote:
> > On Thu, Jun 07, 2018 at 01:42:17PM +, Basile B. via Digitalmars-d
> > wrote:
> > > [...]
> > [...]
> > 
> > You're on the right track. Now all you have to do is to add operator
> > overloading to make the wrapper type infectious, and a convenience
> > function that can be easily typed, and you get:
> > 
> > [...]
> 
> Yeah nice, but it can be more simply used _just_ when the unary
> operator would lead to the message (with ctor: ~SomeType(...).

The same deprecation message appears when doing simple arithmetic with
narrow int types, like `byte b = cast(byte) 10 + cast(byte) 20;`. The
.np wrapper gets rid of all that, with the added bonus of documenting
the programmer's intent in the code.


T

-- 
English is useful because it is a mess. Since English is a mess, it maps well 
onto the problem space, which is also a mess, which we call reality. Similarly, 
Perl was designed to be a mess, though in the nicest of all possible ways. -- 
Larry Wall


Re: Tired by deprecation message for unary operators on 8/16 bit vars ? A simple solution

2018-06-07 Thread Basile B. via Digitalmars-d

On Thursday, 7 June 2018 at 15:18:49 UTC, H. S. Teoh wrote:
On Thu, Jun 07, 2018 at 01:42:17PM +, Basile B. via 
Digitalmars-d wrote:

[...]

[...]

You're on the right track. Now all you have to do is to add 
operator overloading to make the wrapper type infectious, and a 
convenience function that can be easily typed, and you get:


[...]


Yeah nice, but it can be more simply used _just_ when the unary 
operator would lead to the message (with ctor: ~SomeType(...).


Re: Tired by deprecation message for unary operators on 8/16 bit vars ? A simple solution

2018-06-07 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 07, 2018 at 01:42:17PM +, Basile B. via Digitalmars-d wrote:
> I don't know if this is a bug but this works:
> 
> ```
> module runnable;
> 
> struct Byte { byte value; alias value this;}
> 
> void main()
> {
> {Byte b; auto c = ~b;} // no message
> {byte b; auto c = ~b;} // deprecation...
> }
> ```
[...]

You're on the right track. Now all you have to do is to add operator
overloading to make the wrapper type infectious, and a convenience
function that can be easily typed, and you get:

---
/**
 * Truncating wrapper around built-in narrow ints to work around stupid casts.
 */
module nopromote;

enum isNarrowInt(T) = is(T : int) || is(T : uint);

/**
 * A wrapper around a built-in narrow int that truncates the result of
 * arithmetic operations to the narrow type, overriding built-in int promotion
 * rules.
 */
struct Np(T)
if (isNarrowInt!T)
{
T impl;
alias impl this;

/**
 * Truncating binary operator.
 */
Np opBinary(string op, U)(U u)
if (is(typeof((T x, U y) => mixin("x " ~ op ~ " y"
{
return Np(cast(T) mixin("this.impl " ~ op ~ " u"));
}

/**
 * Truncating unary operator.
 */
Np opUnary(string op)()
if (is(typeof((T x) => mixin(op ~ "x"
{
return Np(cast(T) mixin(op ~ " cast(int) this.impl"));
}

/**
 * Infectiousness: any expression containing Np should automatically use Np
 * operator semantics.
 */
Np opBinaryRight(string op, U)(U u)
if (is(typeof((T x, U y) => mixin("x " ~ op ~ " y"
{
return Np(cast(T) mixin("u " ~ op ~ " this.impl"));
}
}

/**
 * Returns: A lightweight wrapped type that overrides built-in arithmetic
 * operators to always truncate to the given type without promoting to int or
 * uint.
 */
auto np(T)(T t)
if (isNarrowInt!T)
{
return Np!T(t);
}

// Test binary ops
@safe unittest
{
ubyte x = 1;
ubyte y = 2;
auto z = x.np + y;
static assert(is(typeof(z) : ubyte));
assert(z == 3);

byte zz = x.np + y;
assert(zz == 3);

x = 255;
z = x.np + y;
assert(z == 1);
}

@safe unittest
{
byte x = 123;
byte y = 5;
auto z = x.np + y;
static assert(is(typeof(z) : byte));
assert(z == byte.min);

byte zz = x.np + y;
assert(zz == byte.min);
}

@safe unittest
{
import std.random;
short x = cast(short) uniform(0, 10);
short y = 10;
auto z = x.np + y;
static assert(is(typeof(z) : short));
assert(z == x + 10);

short s = x.np + y;
assert(s == x + 10);
}

// Test unary ops
@safe unittest
{
byte b = 10;
auto c = -b.np;
static assert(is(typeof(c) : byte));
assert(c == -10);

ubyte ub = 16;
auto uc = -ub.np;
static assert(is(typeof(uc) : ubyte));
assert(uc == 0xF0);
}
---


T

-- 
Public parking: euphemism for paid parking. -- Flora


Tired by deprecation message for unary operators on 8/16 bit vars ? A simple solution

2018-06-07 Thread Basile B. via Digitalmars-d

I don't know if this is a bug but this works:

```
module runnable;

struct Byte { byte value; alias value this;}

void main()
{
{Byte b; auto c = ~b;} // no message
{byte b; auto c = ~b;} // deprecation...
}
```

---
Baz


Re: lazy evaluation of logical operators in enum definition

2018-04-18 Thread Meta via Digitalmars-d

On Wednesday, 18 April 2018 at 10:19:20 UTC, Atila Neves wrote:
On Wednesday, 18 April 2018 at 04:44:23 UTC, Shachar Shemesh 
wrote:

On 17/04/18 13:59, Simen Kjærås wrote:

[...]


Also, extremely dangerous.

Seriously, guys and gals. __traits(compiles) (and its uglier 
sibling, is(typeof())) should be used *extremely* sparingly.


[...]


A very good rule of thumb. I've lost of how many times I've had 
a bug because of __traits(compiles) being false, but not in the 
way I expected it to be!


Let me third that.

Although this would not be as big of a problem if we had a way of 
printing out the values for failed template constraints (isn't 
this already done for static if now?)


Re: lazy evaluation of logical operators in enum definition

2018-04-18 Thread Timon Gehr via Digitalmars-d

On 18.04.2018 09:18, Walter Bright wrote:

On 4/15/2018 10:57 PM, Shachar Shemesh wrote:
It seems that the && evaluation does not stop when the first false is 
found.



Evaluation does stop, semantic analysis does not. For example:

   bool foo() {
     return 0 && undefined_variable;
   }

does not compile. I'd speculate that most would consider this code 
compiling successfully as surprising behavior. It would also be 
difficult to specify, as just when is e1 of (e1 && e2) statically known 
at compile time (i.e. how much flow analysis is the compiler expected to 
do to determine this?).


His use case is `enum x = 0 && undefined_variable;`, for which at least 
your second concern does not apply. It is also surprising that a `static 
if` condition cannot be hoisted out:


---
static if(expression){ ... }
---

---
// not necessarily the same as the above
enum c = expression;
static if(c){ ... }
---

I think the suggestion is to do lazy semantic analysis for all 
standalone expressions that need to be evaluated at compile-time (and 
not just for `static if`/`static assert` conditions).


Re: lazy evaluation of logical operators in enum definition

2018-04-18 Thread Atila Neves via Digitalmars-d
On Wednesday, 18 April 2018 at 04:44:23 UTC, Shachar Shemesh 
wrote:

On 17/04/18 13:59, Simen Kjærås wrote:

[...]


Also, extremely dangerous.

Seriously, guys and gals. __traits(compiles) (and its uglier 
sibling, is(typeof())) should be used *extremely* sparingly.


[...]


A very good rule of thumb. I've lost of how many times I've had a 
bug because of __traits(compiles) being false, but not in the way 
I expected it to be!


Re: lazy evaluation of logical operators in enum definition

2018-04-18 Thread Walter Bright via Digitalmars-d

On 4/15/2018 10:57 PM, Shachar Shemesh wrote:

It seems that the && evaluation does not stop when the first false is found.



Evaluation does stop, semantic analysis does not. For example:

  bool foo() {
return 0 && undefined_variable;
  }

does not compile. I'd speculate that most would consider this code compiling 
successfully as surprising behavior. It would also be difficult to specify, as 
just when is e1 of (e1 && e2) statically known at compile time (i.e. how much 
flow analysis is the compiler expected to do to determine this?).


Re: lazy evaluation of logical operators in enum definition

2018-04-17 Thread Shachar Shemesh via Digitalmars-d

On 17/04/18 13:59, Simen Kjærås wrote:

There's a kinda neat (and kinda ugly) way to implement prop in one line:

     enum prop(T) = __traits(compiles, { static assert(T.member == 3); });

Now, that's not the same as short-circuiting, and only useful in some 
cases, but for those cases, it's useful.


Also, extremely dangerous.

Seriously, guys and gals. __traits(compiles) (and its uglier sibling, 
is(typeof())) should be used *extremely* sparingly.


The problem is that just about any use of __traits(compiles) I know of 
is seeking to weed out one particular reason for the compilation 
failure. There is a known bug in D, however, that the compiler 
consistently fails to read the programmer's mind. The compiler only 
knows that the code as provided does not compile, and that in that case 
you asked for something to happen.


The usual outcome is that 80-90% of the times your code does what you 
expect, but then something comes along that throws you off the beaten 
track. In those cases, instead of getting an error message, you get one 
of the sides of the "if", which results in random behavior by your code.


If you're lucky, you will get an error message much further down the 
compilation line, and then start having a fun day of trying to figure 
out what the !*#()%&!@#)!@( just happened. If you're less lucky, the 
code will actually compile.


My personal rule of thumb is this: If there is *any* way of achieving 
the result I want without __traits(compiles), do it that way.


Shachar


Re: lazy evaluation of logical operators in enum definition

2018-04-17 Thread Simen Kjærås via Digitalmars-d

On Monday, 16 April 2018 at 05:57:01 UTC, Shachar Shemesh wrote:

Consider the following program:

struct S1 {
enum member = 3;
}

struct S2 {
enum member = 2;
}

struct S3 {
}

enum prop(T) = __traits(hasMember, T, "member") && T.member==3;

pragma(msg, prop!S1);
pragma(msg, prop!S2);
pragma(msg, prop!S3);

When compiled, it produces:
true
false
test.d(12): Error: no property member for type S3
test.d(16): Error: template instance `test.prop!(S3)` error 
instantiating

test.d(16):while evaluating pragma(msg, prop!(S3))

If I change the definition of "prop" to:
template prop(T) {
static if( __traits(hasMember, T, "member") && T.member==3 )
enum prop = true;
else
enum prop = false;
}

then everything compiles as expected.

It seems that the && evaluation does not stop when the first 
false is found.


There's a kinda neat (and kinda ugly) way to implement prop in 
one line:


enum prop(T) = __traits(compiles, { static assert(T.member == 
3); });


Now, that's not the same as short-circuiting, and only useful in 
some cases, but for those cases, it's useful.


--
  Simen


Re: lazy evaluation of logical operators in enum definition

2018-04-17 Thread Jacob Carlborg via Digitalmars-d

On Monday, 16 April 2018 at 05:57:01 UTC, Shachar Shemesh wrote:

Consider the following program:

struct S1 {
enum member = 3;
}

struct S2 {
enum member = 2;
}

struct S3 {
}

enum prop(T) = __traits(hasMember, T, "member") && T.member==3;

pragma(msg, prop!S1);
pragma(msg, prop!S2);
pragma(msg, prop!S3);

When compiled, it produces:
true
false
test.d(12): Error: no property member for type S3
test.d(16): Error: template instance `test.prop!(S3)` error 
instantiating

test.d(16):while evaluating pragma(msg, prop!(S3))

If I change the definition of "prop" to:
template prop(T) {
static if( __traits(hasMember, T, "member") && T.member==3 )
enum prop = true;
else
enum prop = false;
}

then everything compiles as expected.

It seems that the && evaluation does not stop when the first 
false is found.


I think the issue is better illustrated with a function:

bool prop(T)()
{
if (__traits(hasMember, T, "member"))
{
if (T.member == 3)
return true;
}

return false;
}

In this function there's no way to tell if the function is going 
to be executed at compile time or at runtime. Therefore the 
semantics of the whole function need to be valid. Replacing the 
`if` with a `static if` would solve the problem, as you 
mentioned. This works because the semantic analysis of `static 
if` and CTFE evaluation of a function occurs at different phases 
in the compiler. This post explains this better and in more 
detail [1]. The issue is that the compiler will do the semantic 
analysis of `T.member` before it has run CTFE or constant folding 
on the expression.


Although, one could argue that in your case it's clear that the 
expression only will be evaluated at compile time, but that's not 
how the compiler works currently.


[1] 
https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time


--
/Jacob Carlborg


Re: lazy evaluation of logical operators in enum definition

2018-04-16 Thread Basile B. via Digitalmars-d

On Monday, 16 April 2018 at 05:57:01 UTC, Shachar Shemesh wrote:

Consider the following program:

struct S1 {
enum member = 3;
}

struct S2 {
enum member = 2;
}

struct S3 {
}

enum prop(T) = __traits(hasMember, T, "member") && T.member==3;

pragma(msg, prop!S1);
pragma(msg, prop!S2);
pragma(msg, prop!S3);

When compiled, it produces:
true
false
test.d(12): Error: no property member for type S3
test.d(16): Error: template instance `test.prop!(S3)` error 
instantiating

test.d(16):while evaluating pragma(msg, prop!(S3))

If I change the definition of "prop" to:
template prop(T) {
static if( __traits(hasMember, T, "member") && T.member==3 )
enum prop = true;
else
enum prop = false;
}

then everything compiles as expected.

It seems that the && evaluation does not stop when the first 
false is found.


Hello, i've encountered a similar issue recently (see 
https://issues.dlang.org/show_bug.cgi?id=18115#c13). There are 
explanations in the last comments.


lazy evaluation of logical operators in enum definition

2018-04-16 Thread Shachar Shemesh via Digitalmars-d

Consider the following program:

struct S1 {
enum member = 3;
}

struct S2 {
enum member = 2;
}

struct S3 {
}

enum prop(T) = __traits(hasMember, T, "member") && T.member==3;

pragma(msg, prop!S1);
pragma(msg, prop!S2);
pragma(msg, prop!S3);

When compiled, it produces:
true
false
test.d(12): Error: no property member for type S3
test.d(16): Error: template instance `test.prop!(S3)` error instantiating
test.d(16):while evaluating pragma(msg, prop!(S3))

If I change the definition of "prop" to:
template prop(T) {
static if( __traits(hasMember, T, "member") && T.member==3 )
enum prop = true;
else
enum prop = false;
}

then everything compiles as expected.

It seems that the && evaluation does not stop when the first false is found.


DIP: Binary assignment operators for properties -- Draft Review

2018-03-08 Thread Mike Parker via Digitalmars-d-announce
The DIP process is on again. I'll be publishing a blog post soon 
describing the changes and their motivation. In the meantime, the 
primary candidate to become DIP 1013 [1] needs a good going over 
for the Draft Review to shake out any structural or technical 
issues. Please see the new Procedure document [2] for a 
description of the Draft Review's purpose.


Please keep any comments regarding the DIP itself in the PR 
thread, rather than this announcement thread.


Thanks!

[1] https://github.com/dlang/DIPs/pull/97
[2] 
https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#draft-review


[Issue 14489] Deprecate Floating point NCEG operators

2018-02-10 Thread d-bugmail--- via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=14489

Iain Buclaw  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 CC||ibuc...@gdcproject.org
 Resolution|--- |FIXED

--- Comment #1 from Iain Buclaw  ---
This has been removed from the spec, and is currently and error in the
compiler.

Not aware of any "gone" status, but that's outside scope of original issue.

--


  1   2   3   4   5   6   7   8   >