Jump to content
  • Advertisement
Kaetemi

What practically annoys you on a regular basis in programming languages?

Recommended Posts

25 minutes ago, Oberon_Command said:

What's unintuitive or odd about this? It's certainly not always convenient, but the idea that comparison operators are binary (and more complex conditions are created by composing them) is a simple and clear one.

What's non-intuitive.. When comparison operators are interpreted from this `(5 < b < 10)` into `((5 < b) < 10)`, which I would argue is useless (comparing a boolean with 10), rather than doing a chained expansion into the more useful `(5 < b && b < 10)`.

EDIT: Just found this recent proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0893r0.html

25 minutes ago, Oberon_Command said:

It seems intuitive enough if you keep in mind that char* as "pointer to string" rather than "string value." I would further argue that this is the correct way to think of a char* and "a == b" in your example is the behavior that I would expect. :)

I can agree with that. How about, assuming a strongly typed typedef mechanism is available, and if I'd typedef `char*` as `cstring`. As the pointer is now "hidden" from the programmer, would it be more acceptable to overload `==` on that `cstring` type?

Edited by Kaetemi

Share this post


Link to post
Share on other sites
Advertisement
7 hours ago, Kaetemi said:

if (5 < x < 10) { }

Clearly you're using the wrong language 😛

From https://docs.python.org/3/reference/expressions.html?highlight=comparison#comparisons

Quote

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

 

Share this post


Link to post
Share on other sites
5 hours ago, Oberon_Command said:

I'd be fine with just automatically calling operator== on each member as the default. We already get that with the implicit copy constructor/assignment operators. If the default doesn't do what I want, I'll override it, but most classes I work with are just doing that, anyway. It's the most usual case and therefore should be the default and automatic one.

My assumption is that the standards committee, being highly concerned with the implementation of the standard libraries, often encounters cases where this is not the default situation. It seems to me that, in general, there is a distinct trend of the standards committee prioritizing library authors when adding new features and rules.

Or perhaps this is an aspect of the "zero cost abstractions" philosophy and the committee doesn't want to force (what I consider) the reasonable default on everyone on the grounds that it would be a default with potential runtime costs. But... we already have that, with copy constructors... And now I'm just speculating.

My expectation here as a C++ programmer would be deep equality, because that's how the standard library types generally behave and how the vast majority of user types I have encountered in production code behave. If I wanted identity rather than equality, I would compare the pointers or similar - eg. handles, in cases where my data is double-buffered or relocatable. If you want to do something else in your own idiom, that's fine, that's why we have operator overloading, but in C++ I'm always going to expect a deep comparison and you should specifically tell me when the type is doing something different.

IMO operator overloading should be reserved for non-default cases and should not be required for holding the compiler's hand through the default ones.

Unless I misunderstand you're getting exactly that, plus auto-generated ordering: https://en.cppreference.com/w/cpp/language/default_comparisons

Share this post


Link to post
Share on other sites
2 hours ago, Eternal said:

Unless I misunderstand you're getting exactly that, plus auto-generated ordering: https://en.cppreference.com/w/cpp/language/default_comparisons

To be clear, what I'm actually looking for is to be able to do this:

struct Point {
  int x;
  int y;
};

Point a = get_point_a();
Point b = get_point_b();
if (a == b) {
  // ...
}

Which currently I cannot, because operator== is not defined automatically. I want the compiler, for simple types, generate an implicit operator== just as it does an implicit copy constructor, without my having to overload anything. Furthermore, my argument is that the reasonable default is member-by-member comparisons.

8 hours ago, Kaetemi said:

I can agree with that. How about, assuming a strongly typed typedef mechanism is available, and if I'd typedef `char*` as `cstring`. As the pointer is now "hidden" from the programmer, would it be more acceptable to overload `==` on that `cstring` type?

A strong typedef doesn't actually change the type, though. It would just disallow implicit conversions with the type it aliases. So no, I wouldn't want a deep compare operator== in that case, because the actual type of cstring is still a pointer type and it still behaves like one in all other respects. "C-string" means "pointer to string." If you wanted to write a wrapper type that did deep equality, that would be fine with me, but then I'd say it should be called something else, like "weak_string" or "string_view" (which we have in the standard!).

8 hours ago, Kaetemi said:

When comparison operators are interpreted from this `(5 < b < 10)` into `((5 < b) < 10)`, which I would argue is useless (comparing a boolean with 10), rather than doing a chained expansion into the more useful `(5 < b && b < 10)`.

I doubt that's really going away any time soon. Booleans being implicitly castable to integers is probably necessary for C compatibility. I suspect there exists at least one "load-bearing bug" that depends on this behavior and changing it would break somebody's code.

Share this post


Link to post
Share on other sites
1 hour ago, Oberon_Command said:

To be clear, what I'm actually looking for is to be able to do this:


struct Point {
  int x;
  int y;
};

Point a = get_point_a();
Point b = get_point_b();
if (a == b) {
  // ...
}

Which currently I cannot, because operator== is not defined automatically. I want the compiler, for simple types, generate an implicit operator== just as it does an implicit copy constructor, without my having to overload anything. Furthermore, my argument is that the reasonable default is member-by-member comparisons.

That's fair, and I don't know why implicit definition of operator== didn't make it, it was proposed at some point. I wouldn't be too surprised if it was just lower priority and will appear in C++23.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!