Live data from Hacker News

C++20 Concepts: The Definitive Guide

thecodepad.com

81–90 of 102 posts

Re: C++20 Concepts: The Definitive Guide

#81

Earlier quoted context omitted.

> I feel like one of the things a "Definitive Guide" to this feature needs to make clear, and maybe even emphasise, is a key way these are different than say Rust type Traits. > Concepts, just like the SFINAE and constrexpr hacks you should discard in their favour, are about only what will compile and you, the C++ programmer, are always responsible for shouldering the burden of deciding whether that will do what you…

The trick is that in Rust the implementer chooses which Traits to implement for their Class while in C++ the Concept chooses what properties it will require and then applies to any classes with matching properties whether that's desirable or not. So in C++ the fact a Mouse is food::LovesCheese doesn't actually tell me whether the Mouse's programmer has any idea what it means to food::LovesCheese or whether the food::…

Okay, now I understand what you meant. Concepts automatically "apply" to anything that satisfies them, whereas Rust traits have to be implemented deliberately.

Thank you for clarifying.

Re: C++20 Concepts: The Definitive Guide

#82
post #59
post #53

Earlier quoted context omitted.

The less you use the new features, the less benefit you get from them. You could stick to K&R C and get no benefit at all, but that would be equally as foolish as what you are doing. The new features are there to improve your experience, and to make your code more reliable. When you have a choice between old and new, new is usually better. Sticking to K&R, you would have as many bugs and crashes as other K&R code. St…

You don’t know what domain the person you are answering works in, so you cannot make such sweeping statements. Implying someone is foolish is plain rude. https://news.ycombinator.com/newsguidelines.html

Anyone can do, or choose not to do, a foolish thing. Encouraging against the foolish thing does not imply anyone is foolish.

Re: C++20 Concepts: The Definitive Guide

#83
post #42

Earlier quoted context omitted.

They are distinct values but they compare equal. For almost all uses they are effectively equal, except where you are producing infinities.

I hadn't thought about the infinities part. If they had the same behavior in all operations involving other numbers, then I could see how they could nonetheless be the same from a C++ type perspective, but given they behave differently, C++ certainly couldn't consider them the same. Thanks for clearing that up!

If you keep infinities and NaNs out of a subsystem, then float and double are totally ordered within that subsystem. So, it is a choice. I would not hesitate on that basis.

Of more moment is that floating point variables often represent imprecise values, such that e.g. 1.41 could represent a value that should equal another transcribed as 1.39. The type system will not help you there. You are obliged to code in tolerance the hard way.

Re: C++20 Concepts: The Definitive Guide

#84
post #11

Another language-changing paradigm added to C++. I haven't even finished learning the old ones yet. Sometimes I think C++ would be better off if the committee stopped accepting proposals that add new features.

Concepts are just nice syntactic sugar for stuff that already existed in the wild for decades, hardly "language-changing".

Re: C++20 Concepts: The Definitive Guide

#85

I feel like one of the things a "Definitive Guide" to this feature needs to make clear, and maybe even emphasise, is a key way these are different than say Rust type Traits. Concepts, just like the SFINAE and constrexpr hacks you should discard in their favour, are about only what will compile and you, the C++ programmer, are always responsible for shouldering the burden of deciding whether that will do what you mean…

> I feel like one of the things a "Definitive Guide" to this feature needs to make clear, and maybe even emphasise, is a key way these are different than say Rust type Traits. What use would that be to a C++ developer who doesn't know rust?

Ah, sorry, I didn't intend that it should address this as "Here's why it's different to Rust" but rather, "Here's a surprising thing about what it does/ doesn't do in your program" and Rust offers a contrast to show this isn't just "But that's how computers work".

As you see from the standard library concepts the emphasis is on semantic claims like "fully ordered" but this feature does not actually provide semantics and I think that's a trap programmers would be likely to fall into.

Re: C++20 Concepts: The Definitive Guide

#86

Earlier quoted context omitted.

> I feel like one of the things a "Definitive Guide" to this feature needs to make clear, and maybe even emphasise, is a key way these are different than say Rust type Traits. > Concepts, just like the SFINAE and constrexpr hacks you should discard in their favour, are about only what will compile and you, the C++ programmer, are always responsible for shouldering the burden of deciding whether that will do what you…

First off, we should be clear what we mean by "guarantee". When you're talking about Rust, "guarantee" means "the compiler enforces this in an ironclad way, such that the programmer cannot mess it up" (generally with the implied caveat that we assume unsafe is not used). C++ programmers generally use "guarantee" to mean "the standard says you should follow these rules", because as the language is not type-safe the co…

You're correct that Rust's compiler can't guarantee semantics. However because the programmer has to actually implement Rust traits, they can and they should.

That option isn't available to C++ because of how concepts work. PartialEq and Eq wouldn't be different concepts in any practical sense, they would just be a funny way to write a comment, but in Rust they are different traits because even though Eq doesn't add any syntax it does add semantics.

There is one further trick I wasn't going to mention but you've sort of brought it up. Rust's unsafe is partly about taking responsibility for the safe and correct operation of your code. That's a pretty alien thought in C++ although I argue it shouldn't have been, it's clearly too late now. As a result Rust has the idea of unsafe traits. If you get PartialEq wrong, the programmer using your type curses and probably discards it as hopelessly broken, but their program mustn't have Undefined Behaviour as a result by Rust's definition.

However if you implement an unsafe trait like Send wrong, maybe the program now has Undefined Behaviour, as a result (signalled by the unsafe keyword you'll need to use to implement it) you are responsible for making sure your implementation is in fact semantically correct.

This distinction wouldn't mean anything in C++ where not only are your implementations of concepts never required to obey the semantics, but the language doesn't even allow you express that your implementation doesn't obey the semantics, the fact it's a syntactic match means it gets recruited by the concept and too bad.

Re: C++20 Concepts: The Definitive Guide

#87

I feel like one of the things a "Definitive Guide" to this feature needs to make clear, and maybe even emphasise, is a key way these are different than say Rust type Traits. Concepts, just like the SFINAE and constrexpr hacks you should discard in their favour, are about only what will compile and you, the C++ programmer, are always responsible for shouldering the burden of deciding whether that will do what you mean…

Rust traits are opt-in, C++ concepts are opt-out; you can think of C++ concepts as having a "blanket" implementation for all types, so you'd need to opt out using negative reasoning. For example, in C++, you can declare a trait:

    template 
    struct totally_ordered : std::false_type {};
and opt-in implement it for some types, but not for floats.

Then you can define a TotallyOrdered concept that requires the trait.

The C++ standard library didn't do this, so if you happen to accidentally implement a type with an API that conforms to TotallyOrdered, then it becomes "accidentally" TotallyOrdered, which is a big footgun.

Re: C++20 Concepts: The Definitive Guide

#88
> The above definition of add is equivalent to the one using static_assert.

They are not though - the equivalent C++17 would be

  template
  std::enable_if_t, T> add(T a, T b)
  {
    return a + b;
  }
The difference is that these make the function unavailable for overload resolution for non-integral T but another implementation might still cover them while the static_assert version leaves the function available for overload resolution but then errors if it is selected.

Re: C++20 Concepts: The Definitive Guide

#90
post #37

Earlier quoted context omitted.

I think there's more to it (changing the language) than you are crediting it. First, you don't have to use the new features (though eventually you'll be reading the code of people who did, so this is only half-valuable). There is new c++11 code being written every day -- in volume (a hard to pin down amount) it's sadly more than 50%. The usage surveys don't really capture this clearly (and it's not clear they could).…

>you don't have to use the new features But it complicates the compiler, complicates the tools, complicates the error messages,... Take something as "simple" as operator overloading. If a beginner does a "5"+5, the compiler is forced to respond with "no operator + for the types given, types are: int, std::string" instead of the infinitely more friendly "can't add string to int". I actually _like_ operator overloading…

> Take something as "simple" as operator overloading. If a beginner does a "5"+5, the compiler is forced to respond with "no operator + for the types given, types are: int, std::string" instead of the infinitely more friendly "can't add string to int".

You are not allowed to overload operators involving only built-in types so operator overloading changes nothing about the expression "5"+5. Even if you could overload operator+ here, there is nothing preventing a compiler from giving you the friendly explanation if that operator does not exist (perhaps with an additional hint that it could be defined).

(Also, the expression "5"+5 is valid C++ but Clang has -Wstring-plus-int to warn you that it might not do what you expect.)

Post reply on HN