[HN Gopher] C++ is an absolute blast
___________________________________________________________________
C++ is an absolute blast
Author : ok123456
Score : 270 points
Date : 2024-12-23 15:37 UTC (1 days ago)
(HTM) web link (learncodethehardway.com)
(TXT) w3m dump (learncodethehardway.com)
| pjmlp wrote:
| While it is a great language, ir would profit from less "lets
| code C with C++ compiler" attitude.
|
| Basically it is like renaming those JavaScript files from .js to
| .ts, and keep coding as if nothing else is available as
| productivity and safety improvements.
| ablob wrote:
| Having read the article, nothing really stands out to me as "C
| with C++ compiler".
|
| It talks about ranges, shared/unique pointers, lambdas...
| Essentially a lot of things C is lacking. I don't know where
| exacly the overlap you're insinuating comes from.
| pjmlp wrote:
| Where did I mentioned the article?
| rickmode wrote:
| Pronoun confusion. The second pronoun is ambiguous.
|
| Since we are all "hackers" here, I'll be pedantic...
|
| "While it is a great language..."
|
| The "it" pronoun clearly refers to the C++ language, as I'm
| sure you intended.
|
| "...ir would profit from less 'lets code C with C++
| compiler ' attitude."
|
| The "ir" -- presumably a typo for "it" -- can refer to the
| article or C++. Given that this thread is about an article,
| the second "it" referring to the article is a natural
| assumption.
| pjmlp wrote:
| It with typo refers to C++.
| thefourthchime wrote:
| I feel like an abused spouse after C++. I now avoid:
|
| - Inheritance - Reference counting - Threading - Templates -
| Classes if possible - Hidden memory allocation - Anything that
| looks clever
|
| Anytime I use them I get flashbacks to some mangled mess of
| templated threaded classes with some memory leak that shows up
| after 3 days.
|
| I remember writing C++ and trying to figure out how the design
| would work between these classes, I would end up with something
| complicated and not entirely correct. Eventually, I thought,
| what if I did this in C? What would it look like, 90% it turns
| out with 90% less design and code (and bugs).
| pjmlp wrote:
| There is no rule that requires "programming in C++ proper"
| being equal with using 100% of the language standard.
|
| There is a middle layer, without having to keep repeating all
| the security flaws of coding in plain C.
| unclad5968 wrote:
| You don't have to use any of that and you still get lots of
| nice things like range based for loops, STL containers,
| algorithms, namespaces, and constexpr.
| xorvoid wrote:
| I'm glad someone is having fun in C++. Personally, after >20
| years, I have to be done with C++. It's just a mess.
|
| If I really need the low-level control, I can wrangle C (warts
| and all), otherwise Rust, Python, etc just make me happier.
| pjmlp wrote:
| Beware of C23 and later.
|
| C is basically going into "we want C++ but without OOP and with
| templates done via _Generic".
|
| Also LLVM and GCC aren't going to be rewritten from C++ into
| Rust anytime soon.
| bilekas wrote:
| > Also LLVM and GCC aren't going to be rewritten from C++
| into Rust anytime soon.
|
| I'm afraid you underestimate the will power of rustaceans to
| find literally anything to rewrite.
| pjmlp wrote:
| I doubt Cranelift will ever match the only project that has
| beaten the contribution level of Linux kernel.
| cornstalks wrote:
| > _Beware of C23 and later._
|
| Beware of what? C23 fixed a number of issues. Sure, there are
| some oddballs (QChar and auto, mostly), but overall I think
| C23 is an improvement.
| pjmlp wrote:
| Those C89 hardliners have a different point of view.
|
| Also there is the whole point Objective-C and C++ are much
| better than those improvements will ever be.
| motorest wrote:
| > Those C89 hardliners have a different point of view.
|
| C89 was only a thing because Microsoft somehow decided to
| drag it's feet and prevented msvc from supporting
| anything beyond c89 for a long, long time. Only in 2020
| did they manage to finally do something about it.
|
| https://devblogs.microsoft.com/cppblog/c11-and-c17-standa
| rd-...
| pjmlp wrote:
| Because for Microsoft C belonged into the past, it was
| about time to move into C++.
|
| https://herbsutter.com/2012/05/03/reader-qa-what-about-
| vc-an...
|
| They only changed of point of view after Satya, and the
| whole Microsoft <3 Linux and Microsoft <3 FOSS pivot.
|
| And in any case, blaming Microsoft doesn't really work
| out, as many of those folks don't even care Windows
| exists, only UNIX/POSIX platforms.
| janice1999 wrote:
| I imagine most C programmers are still using C99 or older
| anyway, particularly in the embedded space.
| ericbarrett wrote:
| I'm not sure this is still true. I'm just a hobbyist but
| esp-idf, for example, supports C++23.
| TJSomething wrote:
| esp-idf is still on GCC 11, but most of the features of
| C23 are in GCC 13.
| phkahler wrote:
| C99 or _newer_. You gotta have standard fixed size types
| like int16_t.
| bcrl wrote:
| Not in the embedded space. When you've worked on embedded
| systems long enough, you learn that you have to accept
| the compiler that the vendor provided you with, and you
| adapt your codebase to the limitations of that compiler.
| This means working around code generation bugs, adding
| #ifdefs to define typedefs for things like int16_t if
| they don't exist.
|
| That said, things are a lot better than they were 15
| years ago, and the mainstream ARM compilers used today
| are leagues better than the barely functional cobbled
| together ports from the early '00s. ARM64 is a tier 1
| platform, and there are enough users of the platform that
| the extended QA team that embedded developers were
| unintentionally part of in the past is no longer really
| the case (at least when it comes to the compiler).
|
| However, there are still truly obscure architectures
| (mostly 8 bit and 16 bit) that continue to have oddball
| compilers. And you accept and deal with that insanity
| because it means you're only paying $0.01 for that
| microcontroller to blink an LED when some kind of an
| event occurs.
| uecker wrote:
| What part of C23 makes you believe this?
| pjmlp wrote:
| Everything that was taken from C++, and _Generic.
|
| And the ongoing discussion for lambdas that didn't make it
| into C23, but still on the table for C2y.
|
| Meanwhile, zero progress in what actually matters, proper
| strings and arrays, that aren't a continuous source of
| memory corruption bugs.
| yodsanklai wrote:
| Agree. C++ is here to stay though. Too much code written in
| that language. It's certainly a great skill to have, and there
| are super lucrative jobs too.
|
| For me, I feel the language just go in the way and is way too
| complex. Sure, I know the discourse: "modern C++" is great, you
| don't need to learn about older. versions of C++, things are
| getting simpler with each new version.
|
| The problem is that the codebase you get to work on aren't
| modern C++. They use every possible feature ever released and
| it's just hard and full of pitfalls.
|
| I suppose people who have only work on C++ in their projects
| for years can develop some level of expertise and are immune to
| the complexity. But really, not a great language...
| jandrewrogers wrote:
| One of the things that has made C++ more tolerable over time is
| that it became easy to seamlessly replace most of it with an
| implementation that works the way you think it should and with
| most behaviors being fully defined -- the core data types,
| standard library, etc. Particularly with C++20 and later,
| alternative foundations feel quite native and expressive.
|
| Most new C++ projects I see lean into this quite heavily. The
| ease with which you can build a systems-level DSL for your
| application is a strength of C++.
| mst wrote:
| There's a parallel here with modern applications perl as
| compared to the crawling horrors people perpetrated in CGI
| scripts during the dot com boom.
|
| Also present day javascript (the language; the ecosystem is
| another matter ;) compared to the 'var' and IIFEs-for-scoping
| era.
| motorest wrote:
| > I'm glad someone is having fun in C++. Personally, after >20
| years, I have to be done with C++. It's just a mess.
|
| I've spent a couple of decades working with C++, and the truth
| of the matter is that, as much as it pains the bandwagony
| types, C++ became great to work with once C++11 was rolled out.
| The problem is that teams need to port their projects to >C++11
| and that takes an awful lot of work (replace raw pointers with
| smart ones, rearchitect projects to shed away C-style
| constructs, etc) which some product managers are not eager to
| take.
|
| I firmly believe that the bulk of this irrational hatred
| towards C++ comes from naive developers who try to rationalize
| away their lack of experience by blaming everything on the
| tool. On top of this, cargo-cult mentality also plays a role.
|
| What makes this quite obvious is the fact that the solution
| presented to all problems always comes in the form of major
| rewrites, even with experimental and unproven features and
| technologies. Writing everything again is always the solution
| to everything. Everyone before them knows nothing whereas these
| messiah, cursed with being the only ones who see the one true
| answer, always have a quick and easy answer to everything which
| always boils down to rewriting everything from scratch with the
| flavor of the month. Always.
|
| Weird, huh?
| ModernMech wrote:
| > C++ became great to work with once C++11 was rolled out.
| The problem is that teams need to port their projects to
| >C++11
|
| The problem is the C++ that's not great to work with is still
| there, and there's nothing preventing the rest of the world
| from using it; there are always going to be naive developers
| with a lack of experience who don't know how to use the tool.
| For this reason, all the code that's possible to write in C++
| will be written, that includes the unsafe code.
|
| It's not enough to have a safe, nice, modern, subset of C++
| that everyone "should" use. If developers have the option to
| use the warty, sharp, foot-gun infested version of C++ they
| will, and they will gift that code to the rest of us in the
| form of readily exploitable software.
|
| This is why organizations like CISA are suggesting developers
| move to other languages that take a stricter posture on
| memory safety: https://www.cisa.gov/news-events/news/urgent-
| need-memory-saf...
|
| > companies should investigate memory safe programming
| languages. Most modern programming languages other than C/C++
| are already memory safe. Memory safe programming languages
| manage the computer's memory so the programmer cannot
| introduce memory safety vulnerabilities. Compared to other
| available mitigations that require constant upkeep - either
| in the form of developing new defenses, sifting through
| vulnerability scans, or human labor - no work has to be done
| once code is written in a memory safe programming language to
| keep it memory safe.
| motorest wrote:
| > The problem is the C++ that's not great to work with is
| still there, and there's nothing preventing the rest of the
| world from using it;
|
| That's precisely why all this criticism is actually thinly
| veiled naive inexperient developers blaming the tools.
| Selling full rewrites as solutions to the problems they
| created is a telltale sign. As they are lacking the
| experience and know-how to fix the mess, they succumb to
| the junior dev disease of believing deleting everything and
| starting from scratch is a solution to all of life's
| problems and inconveniences.
| grumpyprole wrote:
| > naive inexperient developers blaming the tools
|
| That's not the problem. It's naive inexperienced
| developers _using_ the tools. Most developers have to
| maintain code they didn 't write themselves. One can
| learn all the C++ best practices in the world, but it
| won't protect you from _other people_. That 's why
| languages with strong restrictions and constraints that
| force safety and correctness are needed. With such
| languages, naive inexperienced developers won't be able
| get anything to compile. We won't have to deal with their
| mistakes as they'll never be able to ship them. Any
| experienced developer would surely want this.
|
| A rewrite is not pointless if you are rewriting into a
| language with additional guarantees. You are checking for
| and proving the absence of certain classes of software
| flaws by doing so.
| lll-o-lll wrote:
| > With such languages, naive inexperienced developers
| won't be able get anything to compile.
|
| Hey dude, I can't get this thing to compile?
|
| Just wrap all your variables in Arc; that's what I always
| do.
| wiseowise wrote:
| I don't see how juniors, who want to rewrite things, are
| the reason why C++ has 3 freaking ways to initialize a
| variable.
| davisp wrote:
| There's a few more than three.
|
| https://leanpub.com/cppinitbook
|
| https://www.reddit.com/r/ProgrammerHumor/comments/8nn4fw/
| for...
| zahlman wrote:
| > C++ became great to work with once C++11 was rolled out.
|
| Have Yossi Kreinin's objections
| (https://yosefk.com/c++fqa/defective.html) been addressed
| yet? In particular, can I reuse source code from another file
| without a text preprocessor yet? Can I change a class'
| private members without recompilation, or am I still stuck
| with indirecting that behind a "pImpl" pointer in the class
| declaration in the header file? (Being able to use a smart
| pointer for that is not addressing the problem.) Are compiler
| error messages resulting from type mismatches reasonably
| short (without third-party tools like STLFilt) yet (never
| mind whether they're informative or pleasant to decipher)?
|
| I know that "some parts of the FQA are not up to date with
| C++11 [and onward]", but I haven't heard of these problems
| being fixed.
| motorest wrote:
| > Have Yossi Kreinin's objections
| (https://yosefk.com/c++fqa/defective.html) been addressed
| yet?
|
| A cursory read of that list is enough to see it's a list of
| complaints fueled by a mix of ignorance and disingenuity.
|
| For example, the first entry complaining about "no compile
| time encapsulation" is somehow completely ignorant and
| oblivious to very basic things such as the pimpl idiom. I
| mean, this thing is notorious in the way it allows Qt to
| remain binary compatible across even major version bumps.
| And yet, "This makes C++ interfaces very unstable"?
|
| The list reads like pure nonsense, to be quite honest. At
| some point the author gripes over the lack of garbage
| collection. Which language lawyers know very well that
| until somewhat recently C++ standards actually had
| provisions to explicitly support it, but whose support was
| removed because no one bothered with it.
|
| Is this your best reference?
| zahlman wrote:
| Yossi is aware of the pImpl idiom and refers to it
| explicitly in section 16.21 of the FQA. It adds the
| overhead of indirection; in particular, it means that
| even when you don't use polymorphism and were able to
| avoid the cost of a vtable, you still don't get to have
| an array of instance data contiguously in memory. And
| it's still something you have to do manually; you don't
| get it by default. It seems clear to me that this simply
| doesn't meet Yossi's standard for "compile time
| encapsulation".
|
| >At some point the author gripes over the lack of garbage
| collection. Which language lawyers know very well that
| until somewhat recently C++ standards actually had
| provisions to explicitly support it, but whose support
| was removed because no one bothered with it.
|
| Other people not caring about garbage collection doesn't
| mean it's a missing feature. It's clear why operator
| overloading in particular would benefit from the ability
| to make temporaries without worrying about the memory
| they allocate. (Of course, this was written in an era
| with a much poorer ecosystem of "smart pointers".)
|
| >Is this your best reference?
|
| It's not as good of a reference as I remember it being, I
| suppose. It _has_ been a long time. But what I 've seen
| of C++ in the interim, bit by bit, has generally made me
| less inclined to pick it up again, not more. The
| complexity just doesn't seem justified.
| markus_zhang wrote:
| I take a few features from C++ in my C++/SDL2 Ultima spinoff
| project -- never completed sadly. Class, std::function,
| std::unordered_map, std::string, std::unique_ptr<type> are the
| only ones that I could recall.
|
| I can't imagine reading other people's code though, unless it's
| in a similar style. I did find that the most difficult part is
| to get past the programming patterns (such as Visitor pattern)
| as I don't write large programs professionally.
|
| I wish C++ stopped at C++/11. The committee seems to want to
| include everything into it at the moment. Maybe C++ is sort of
| ULTRA programming language that supports every niche
| programming style.
| jandrewrogers wrote:
| FWIW, C++20 is a _much_ tidier and more usable language than
| C++11. The difference between C++11 and C++20 is almost as
| large as C++11 and legacy C++.
| tcbawo wrote:
| What is your Ultima spinoff project?
| markus_zhang wrote:
| Ah that was my pet project to create an engine that runs a
| game similar to Ultima 1-3. I even used the Ultima 4 sprite
| sheet. Never completed it though.
| mort96 wrote:
| C++ is an absolute mess.
|
| But it's a fun mess, and I like writing in it :) Sometimes,
| that's important.
|
| My relationship with, say, Rust is much colder: I respect Rust,
| I use Rust where I think it makes sense (especially in e.g
| professional contexts where I often can't defend the use of
| C++), and I think what it's doing is important. But I find it
| tedious to write, despite having a fair amount of Rust projects
| under my belt at this point. It's better in key ways, but not
| as _enjoyable_ , for me.
| scotty79 wrote:
| Rust is fun for me but I keep it high level with Rc and
| built-in data structures. It's fun thinking about variables
| as little boxes of fixed size that values get moved into or
| out of. It's so different than almost any other language
| where stuff lies often god knows where and is referenced ad
| nauseam. Although that can be fun too if the language treats
| mutability as exception rather than a rule.
| amelius wrote:
| Same. I wish someone made a better C++ from a blank slate. And
| no it's not Rust.
| zahlman wrote:
| Is Rust not meant to offer the same kind of control and "low-
| level-ness" as C? Like, can't you cast integers to pointer
| explicitly if you break the `unsafe` seal (and thereby e.g. do
| memory-mapped IO to control hardware)?
| NotGMan wrote:
| The problem with any language trying to replace C++ for larger
| codebases is that it's not half as powerful as C++.
|
| I've often cursed in C# because something that could be done
| trivially in C++ if impossible and causes the dev to create
| convuluted C# while it could be trivialy done in C++ due to its
| very expressive language features.
|
| Those 0.1% of the time that you need those extreme features are
| what makes or breaks the language in PRODUCTION.
| sidpatil wrote:
| What are some examples of these C++ features you've missed in
| other languages?
| pixelpoet wrote:
| Zig not having operator overloading makes it suck horribly
| for writing any kind of vector code. If everyone had to write
| int a = int_add(int_mul(3, 7), 2) etc there would rightly be
| a riot, but since they're not 3D coders they just don't give
| a shit. Too bad, Zig looks great.
| pixelpoet wrote:
| Sorry, one more thing to add to this: Andrew Kelley is
| obviously a genius, and his talk introducing Zig[0] is in
| my top 10 of all time technical presentations, for many
| reasons. But I really do wish someone close to him with a
| passion for how coding is in many ways applied mathematics,
| would ask him to please have broader algebraic support for
| basic operations like +, -, * and maybe divide, with their
| basic dataflow characteristics. Optimal speed for complex
| numbers vs std::complex out of the box would be attractive.
|
| I understand his point about not wanting to allow every
| random C++ feature, but in these cases, it isn't a C++
| feature, it's language-level basic algebra.
|
| In C++ land, ISPC[1] is often what you use when you want
| top speed rendering perf on SIMD CPUs, e.g. Moonray
| project[2]
|
| Please, just go ahead and define a nice clean API for
| vectors and scalars like OpenCL provides on its beautiful
| reference cards:
| https://www.khronos.org/files/opencl-1-2-quick-reference-
| car...
|
| [0] https://www.youtube.com/watch?v=Gv2I7qTux7g
|
| [1] https://ispc.github.io/
|
| [2] https://openmoonray.org/
|
| Final edit sorry: in the end I love C++ and have been
| learning Rust mainly out of curiosity. Avoiding C++ quirks
| one can have few problems and a great time.
| uzerfcwn wrote:
| Once, I wanted to write a C# function roughly like this:
| (T1, ..., Tn) Apply<T1, ..., Tn>((Func<P, T1>, ..., Func<P,
| Tn>) args)
|
| This is not possible in C# because the language doesn't have
| variadic generics. Instead, I used runtime reflection and
| wrote something like this: object[]
| Apply(Func<P, object>[] args)
|
| Although it worked, the downside is that the types T1, ...,
| Tn are no longer statically known, which means that the
| function's contract has to be written in comments and the
| caller has to check them manually. In contrast, C++ has
| variadic templates, which would allow the compiler to check
| the types automatically.
| blharr wrote:
| I've had the exact same experience, but opposite. Tons of
| things that are trivial in C# take a ton of code in C++ to me.
| Maybe it's just going from being an expert in one language to a
| newer language?
| neonsunset wrote:
| This often comes from expecting C# to be _just_ like C++,
| where-as more complex use cases are often expected to be done
| in a (sometimes completely) different way there. It 's a good
| idea to try not to fight the language and work _with_ the way
| it exposes its features.
|
| My experience was just like yours - easy to move between C
| and C#, or Rust and C#. But attempting C++ implementation was
| always far more difficult. It was never worth it over just
| spending extra effort in either alternative.
|
| If GP reply author has C#-specific questions I'd be happy to
| answer or point him or her in the right direction. C# is a
| language with strong systems programming capabilities but has
| its own learning curve.
| ykonstant wrote:
| That claim certainly warrants a serious example. Perhaps you
| mean "something ... requiring maximum performance ..."?
| tester756 wrote:
| >I've often cursed in C# because something that could be done
| trivially in C++
|
| e.g?
| GlenTheMachine wrote:
| OK, so I admit I also washed my hands of C++ sometime around 2009
| and I am being forced back into for <reasons>, and I had no idea
| what these auto and lambda keywords were.
|
| Can anyone point me to a learning reference that will let me jump
| the meta programming apocalypse and just get to the good stuff?
| seanthemon wrote:
| jump into learncpp and choose where to start from, goodluck
| olvy0 wrote:
| The "Back to Basics" videos from cppcon are pretty good, IMO.
|
| For lambdas: Back to Basics: Lambdas - Nicolai Josuttis -
| CppCon 2021
|
| https://www.youtube.com/watch?v=IgNUBw3vcO4
|
| Back To Basics: Lambda Expressions - Barbara Geller & Ansel
| Sermersheim - CppCon 2020
|
| https://www.youtube.com/watch?v=ZIPNFcw6V9o
|
| For auto, this one is short and summarizes some of the gotachs:
|
| C++ Weekly - Ep 287 - Understanding `auto`
|
| https://www.youtube.com/watch?v=tn69TCMdYbQ
| vitaut wrote:
| > C++ has built-in regex now and they're pretty damn good too
|
| Sadly, `std::regex` is anything but good (poor performance, lack
| of Unicode support) and should be generally avoided.
| yodsanklai wrote:
| The linter used at my work insists on not using it....
| fooker wrote:
| Is there something wrong with the specification that causes
| poor performance?
| steveklabnik wrote:
| It's ultimately a "won't break ABI" issue:
| https://stackoverflow.com/a/70587711
| johannes1234321 wrote:
| The underlying issue is that for the matches the interface
| relies a lot on heap allocations for the individual matches,
| leading to a lot of allocations of small regions to copy from
| the original input. Many other libraries provide a lot more
| control there.
|
| In benchmarks std::regexp often is a lot slower compared to
| other implementations, independent from the standard library
| implementation of choice.
|
| The big upside compared to all others is that it's always
| available. But if there is a choice alternatives are often
| better.
| sumuyuda wrote:
| I'm not for sure auto is an improvement. I know it is required
| for lambdas and it makes it easier to type out a very verbose
| type, but it really does reduce code readability.
|
| I've even seen developers use it instead of bool, which is pretty
| laughable as the they are the same number of characters.
| wk_end wrote:
| A verbose enough type - and C++ has plenty of those - is
| indistinguishable from line noise.
|
| There are places where having an explicit type annotation can
| improve readability, places where it harms readability, places
| where it doesn't make much difference one way or another.
| Giving us the option has been a blessing. All programming calls
| for good taste, C++ programming calls for it more than most.
| BeetleB wrote:
| > but it really does reduce code readability.
|
| How about not specifying the type, and letting the compiler
| infer it correctly and error out when it cannot - like so many
| other languages do? And those languages are much _stricter_
| about types than C++.
|
| And auto _reducing_ code readability? Having to figure out the
| intricacies of a detailed type to write was a huge barrier, and
| virtually anyone reading the code with a type involving several
| nested angle brackets would not bother mentally parsing it
| anyway.
| Leherenn wrote:
| I think it does reduce readability in some scenarios.
|
| For instance: const auto& processes =
| getCurrentlyRunningProcesses(); for (const auto& process:
| processes) { // Ok, what do I do with process now? Is it a
| pair from a map? A struct from a vector? // If it's a pair
| from a map, is the key the pid, a unique id, something else?
| }
|
| std::unordered_map<Pid, ProcessData> is more readable than
| auto here IMO: you don't need to open the definition (or hope
| your IDE correctly display the type).
| jamesfinlayson wrote:
| I remember reading something here recently about auto causing
| some painful and difficult to diagnose bug - I think string was
| what they thought the type should be (and some implicit cast
| would have made it a string if the type was specified)... but
| instead it created a string_view which went on to be used
| somewhere that accepted both string and string_view and then
| something tried to use it later but whatever the string_view
| was pointing to was gone (or something in that vein - I don't
| recall exactly).
| xonre wrote:
| It's probably auto when you wanted auto&.
|
| A copy was made instead of a reference. I've been bitten by
| that.
| ansgri wrote:
| Auto is an improvement for C++ only because of its uniquely
| unergonomic type system and standard library. I'd very much
| prefer writing something like `iterator<auto>` instead of
| `auto` or `std::map<lotsofchars>::iterator` and not be told by
| every linter to change most explicit type declarations to
| `auto`.
| SloopJon wrote:
| This is a long rant that covers a lot of ground, a lot of which
| will inevitably be ignored because the letters "C++" trigger
| people, myself included sometimes. (Skip ahead to "It's Not All
| Puppies and Butterflies" for some of the complaints.) The author
| is really impressed by C++11, as am I, after purposely ignoring
| C++ for the better part of twenty years.
|
| I appreciate the shout outs to some packages and libraries to
| play with, although I still often find it a pain to incorporate
| other libraries into my projects. (Single-file headers, anyone?)
| I'm intrigued by FTXUI.
|
| And boy, howdy, he's right: cppreference.com is amazing. Python's
| documentation is pretty good, but I've never seen anything as
| good as cppreference.com.
| zahlman wrote:
| cppreference.com is very, very good at being _reference_ , as
| in the name.
|
| Python's documentation is scattershot and incomplete in many
| places, and lacks a consistent copy-editing style - but it
| offers good coverage of all kinds of documentation (per the
| Diataxis framework), not just reference. The people writing
| that documentation explicitly take that framework into
| consideration and use it to look for ways to improve. (But it's
| still a volunteer effort that works basically the same way the
| code development does, following open-source principles, so.)
| tecoholic wrote:
| The article filled me on a lot of things I didn't know about
| C++ because I learnt it at school and college, but soon moved
| to Python/JavaScript for day job. I have been itching to "get
| closer to the system" for a while now, and learning Rust on the
| side hasn't been easy. This article gave me hope that, I might
| be able to do that if I refreshed C++. Hello CMake... or I
| should probably say, Meson.
| DidYaWipe wrote:
| I've had some good times in C++. But for everything that's been
| thrown into it, I can't believe we're still dealing with header
| files. That was one of the greatest things about moving to Swift:
| no more of that BS.
|
| But with SwiftUI, Swift has also become "unfun." SwiftUI and
| Apple's half-assed, broken observation and "reactive" paradigm
| have made programming a joyless slog.
| badpun wrote:
| C++20 has modules, which replace header files completely
| (unless you use old libraries which aren't available as modules
| yet). Compiler support is there, but unfortunately IDEs are
| lagging. If you use modules with Visual Studio, say goodbye to
| IntelliSense. Maybe they'll iron out the bugs in a couple
| years...
| DidYaWipe wrote:
| Wow, that's ridiculous.
|
| I wonder if Xcode does any better with them. Now that would
| be something.
| ModernMech wrote:
| C++ has modules for small values of "modules":
| https://arewemodulesyet.org
|
| It's a bit tongue in cheek but: "Are we modules yet? Nope.
| ... Estimated finish by: Wed Sep 20 2541"
| badpun wrote:
| You can use modules to structure your own codebase. No more
| need to write headers and think about how to structure your
| code in terms of compilation units. But yeah, your link
| shows that practically none of the popular libraries
| (except STL) can be imported as modules today.
| wiseowise wrote:
| C++20 that is not complete in 2025. I don't know how C++
| developers can work in this with a straight face.
| metaltyphoon wrote:
| You probably have to think this way: Anything added to C++
| will only get to be used in for real for real in 10 years
| minimum.
| lyu07282 wrote:
| They needed the most powerful, most flexible module system
| ever, so it might take decades to really become useable.
| Adoption has been painfully slow so far, it's insane
| complexity really doesn't help.
| sumuyuda wrote:
| I did C and C++, then moved on to Objective-C and Swift. I
| recently switched back to C++, after getting tired of Apple's
| shit treatment of developers. I also have no interest in
| learning SwiftUI.
|
| Having to define header files in C++ is pretty annoying after
| doing Swift for many years.
| motorest wrote:
| > I've had some good times in C++. But for everything that's
| been thrown into it, I can't believe we're still dealing with
| header files.
|
| There is nothing wrong with header files. In fact, there is no
| such thing as a header file specified in C++. There are only
| forward declarations and definitions, and how those can be
| managed by developers.
|
| Meaning, any talk about header files is a discussion on
| software engineering practices, and how developers create or
| avoid their own problems.
| DidYaWipe wrote:
| "There are only forward declarations and definitions, and how
| those can be managed by developers."
|
| Why do we need to manage them?
| motorest wrote:
| > Why do we need to manage them?
|
| Why do developers need to write code that makes sense and
| does what they want it to do?
| DidYaWipe wrote:
| Enjoy your echo chamber.
| motorest wrote:
| > Enjoy your echo chamber.
|
| Is that supposed to mean anything at all?
| BeetleB wrote:
| Why do developers in other languages not have to deal
| with it?
| motorest wrote:
| > Why do developers in other languages not have to deal
| with it?
|
| They do, except they don't have the bandwagon effect
| motivating them to complain about other solved problems.
| amelius wrote:
| Because nobody has figured out a way to automate the
| process of generating declarations from definitions.
| 01100011 wrote:
| I periodically work on c++ instead of C and each time it follows
| a similar pattern where I learn about some new c++ trick, think
| it will make things better, write my code, hit a compiler error,
| then spend the rest of the day learning why I can't do what I
| want. Granted, I usually am stuck at c++14, and some of the
| issues are fixed in future versions but still...
|
| I really want to love C++. It gives me a more powerful C that
| theoretically should improve my output but in the end it carries
| so much cognitive baggage that I usually end up writing "C with
| classes" and move on.
| blastonico wrote:
| chatgpt or copilot helps a lot with that. I usually copy the
| text and let it decipher the thing for me.
| mithametacs wrote:
| they're still bad for generating any significant body of
| code.
|
| They're a little bit better about deciphering errors.
|
| They'll still bullshit* you and send you on wild goose
| chases.
|
| *hallucinate if you prefer
| matheusmoreira wrote:
| > They'll still bullshit you and send you on wild goose
| chases
|
| And confidently at that. It can't seem to find the backbone
| to say no to me either.
|
| If I say something like "wait, X doesn't seem to make
| sense, isn't it actually Y and Z?" it will agree and
| reformulate the answer as if Y and Z were correct just to
| placate me. I usually use the LLM to learn new things, I
| don't don't actually know if Y and Z apply.
| fooker wrote:
| C++, like most technology, works better if you put in the work
| to learn about it.
|
| (Admittedly there are languages like python and ruby that buck
| this trend.)
| motorest wrote:
| > C++, like most technology, works better if you put in the
| work to learn about it.
|
| There's also the impact of software entropy: if someone has
| little to no experience developing software and has to grow
| it by adding features and fixing bugs, over time their
| contribution to the project invariably results in degrading
| it beyond the point they can possibly salvage it.
|
| At that point, they blame the tools.
| Symmetry wrote:
| Sure, but the effort/reward ratio bears some consideration.
| I've put a lot more effort into learning C++ than any other
| programming language but I'd still say it's just the language
| I'm maybe 4th most proficient in.
| 01100011 wrote:
| Programming languages are a means to an end. I'd rather have
| my cognition going towards solving the actual problem and not
| worrying about implementation details.
| zahlman wrote:
| Python _does_ work better if you put in that kind of work.
| Otherwise you 'll get bit by the way mutable default
| arguments work[0] (or never learn to use it to your
| advantage), or by late binding of closures[1] (and maybe
| you'll pick up the awful habit of _exploiting the confusing
| early binding of default arguments_ to make the `lambda`s
| that you constructed in a loop work properly[2]). Or you won
| 't get the big picture of the descriptor protocol[3] and how
| method lookup[4] is related to the implementation of
| properties[5]. Or you won't get the fancy metaclass[6] thing
| that your favourite framework is expecting you to treat as an
| opaque abstraction[7], or how and when you might use a class
| decorator[8] instead of a metaclass to do that kind of
| metaprogramming.
|
| [0]: https://stackoverflow.com/questions/1132941
|
| [1]: https://stackoverflow.com/questions/2295290
|
| [2]: https://stackoverflow.com/questions/3431676
|
| [3]: https://docs.python.org/3/howto/descriptor.html
|
| [4]: https://eev.ee/blog/2013/03/03/the-controller-pattern-
| is-awf... (yes, this was partly an excuse to get one of Zed
| Shaw's critics [9] into the discussion)
|
| [5]: https://stackoverflow.com/questions/3798835
|
| [6]: https://stackoverflow.com/questions/100003
|
| [7]: e.g. https://medium.com/@miguel.amezola/demystifying-
| python-metac... - I didn't have a good link for this and
| didn't spend a long time searching, but this seems okay
|
| [8]: https://stackoverflow.com/questions/681953
|
| [9]: https://eev.ee/blog/2016/11/23/a-rebuttal-for-python-3/
| gopalv wrote:
| > then spend the rest of the day learning why I can't do what I
| want
|
| There's a point when learning's fun, I think the OP is still
| there.
|
| I wrote a bunch of realtime C++ in 2003, hated it. But last
| year, I wrote most of my code in C++ and liked it finally.
|
| Lambda and auto was the tipping point where I stopped hating
| it. Some templates thrown in, but mostly to avoid writing a lot
| of branches for variants of the same function.
|
| With lambdas I could now write the way I was initially taught
| programming, mostly by Lispy teachers channeling SICP.
|
| Didn't hate the allocations either with unique_ptr.
| hashishen wrote:
| "Lispy teachers channeling SICP" made new audibly laugh
| cshokie wrote:
| If you haven't already look up 'if constexpr' in cpp17 and
| newer. It lets you have compile time branches in a single
| function.
| mst wrote:
| Also requires, which initially looks batshit insane but is
| in fact really quite cool: https://www.think-
| cell.com/en/career/devblog/if-constexpr-re...
| scotty79 wrote:
| > There's a point when learning's fun, I think the OP is
| still there.
|
| What a horrible idea that one might no longer be there.
| mystified5016 wrote:
| This describes my C++ experience precisely. Initially I was a
| C# programmer learning C for embedded projects and it went
| exactly like this.
|
| C++ has a lot of really neat features that sure look powerful
| if your application aligns precisely. It seems like _every_
| time I try a new feature, what I want to do is always an edge
| case that doesn 't work in my situation. I try for a few
| hours/days before I give up and just write it in C.
| bcrl wrote:
| My biggest disappointment with C++ is that the standard
| libraries are completely unsuitable for use in embedded
| systems where you have to control when, where and how many
| memory allocations occur. This is particularly important when
| the system level design choice is to perform all allocations
| at system startup, which is a common design pattern for high
| performance systems with real time characteristics. A high
| speed messaging system I worked on ran into this all the
| time. We couldn't use the standard implementations of things
| like heaps, hashes or queues because they don't have a way of
| making memory allocations occur at startup. It was quite
| common to have to re-implement those data structures when
| adding a new feature, as the stl or boost implementations
| were not suitable for this design pattern.
| swordzen wrote:
| Have you tried override the allocators and destructors of
| your classes so you can do all allocations at startup?
| ahartmetz wrote:
| I see a lot of bad code from people who have just learned about
| some feature and want to use it. Don't do that. Think of how to
| write your code, and then, if a feature solves a problem, use
| it. Problem->Solution, not the other way around.
|
| E.g. C++ templates are generally pretty awful, but sometimes,
| compile-time duck typing, or automatically adding padding based
| on sizeof(), etc, is very useful.
| liendolucas wrote:
| A bold statement from Ken Thompson on C++:
| https://m.youtube.com/watch?v=c-P5R0aMylM
| blastonico wrote:
| The amount of high performance, production grade, massively
| tested libraries written in C++ is unbeatable. I will be honest
| here, it's easier to improve C++ security by implementing a
| compiler that produces safer C++ (like Typescript to Javascript)
| than rewriting everything in any other language (Rust, Zig, Odin,
| whatever).
|
| I mean, could you estimate the cost ($ and time) it would take to
| rewrite the best audio framework in any other language?
| (https://juce.com/).
| devjab wrote:
| Zig is great, it's not aiming to be a replacement for C++
| though. One of the awesome things about Zig is its
| interoperability with C. In that sense it's more of a
| Typescript to C than Rust is to C++. I'm still not sure what I
| think about Rust personally. In my region of the world I
| suspect it'll continue to struggle to find any form of adoption
| as the C++ people seem to have very little interest in trading
| their decade long experience for Rust. Zig on the other hand is
| winning the hearts and minds of most C programmers I know.
|
| I hope Rust succeeds though. I say this more from a change
| management perspective than anything else. It's extremely hard
| for us to find developers who will primarily work with garbage
| collected languages but occasionally have to work with either C
| or C++ when bottle necks appear. Rust makes that much easier,
| or perhaps less dangerous would be a better term. I'm not sure
| any of the attempts at making C++ more safe to use is going to
| really succeed in this regard. Maybe, but I nothing within the
| C++ community seems to pull in that direction so I doubt it.
| I'd like to mention that I'm aware that Zig isn't helpful in
| this regard either as it's not memory safe.
| zahlman wrote:
| How many total lines of code do you imagine are in these
| libraries, compared to _all their clients_? If rewriting the
| libraries sounds like an unreasonable amount of work in a world
| where all that client code exists, doesn 't that reflect
| negatively on the readability of C++?
| FpUser wrote:
| Agree. Sure there are problems here and there but I think that
| overall modern C++ is likely the most versatile tool in the
| "compiled to native, can do anything" family
| jonstewart wrote:
| Every time I try to use Rust instead of C++, I'm left asking
| "bruh, do you even functor?"
| macawfish wrote:
| Using c++ after learning rust feels like picking through moldy
| bread
| hypeatei wrote:
| Using C++ after Rust made me appreciate the latter a lot more.
| You quickly learn all the footguns that the compiler stops you
| from doing and is generally a good learning experience.
| ModernMech wrote:
| This is what I feel as well. I liken it to using an aimbot in
| Quake. Turn off the aimbot and you still win because the
| aimbot trained you how to get headshots. There are many times
| the Rust compiler told me I couldn't do something I had
| insisted would be fine, only to ponder and realize in fact
| what I was doing would cause subtle bugs in an edge case.
| Rust catches it at compile time, C++ allows you to write the
| code and sends you a segfault when the subtle edge case
| occurs in production.
| chowells wrote:
| Segfaults in production are the _good_ case. They 're when
| the system recognizes you've made a mistake and stops it
| from propagating. The bad cases are when the program keeps
| running but silently does the wrong things.
| spacechild1 wrote:
| Yes! This can be a real problem when your data structures
| are allocated from a memory pool. Since the whole memory
| region is owned by the program, out-of-bounds writes will
| either do nothing or silently corrupt your program state.
| ModernMech wrote:
| The good case is that you catch the error in development
| and it doesn't even get to production.
| plandis wrote:
| Plus the Rust compiler actually gives you helpful error
| messages. C++ compiler errors might as well be in Klingon.
| marcosdumay wrote:
| Strings!
|
| Strings in Rust aren't that great, because there are some
| details you must keep track. But when I was first learning it,
| I eventually had some desire to rewrite stuff in C++, and
| always stopped at the first thought of dealing with strings.
| aleden wrote:
| For the love of God when will c++ compilers finally be able to
| output template errors that aren't completely expanded and are
| written in terms of the user's typedefs? Most of the time I spend
| parsing template errors with boost is just to figure out what the
| hell is being complained about.
| ModernMech wrote:
| I have found LLMs are a great tool for metaprogramming. I think
| the template error problem has been wanting for a sufficiently
| advanced compiler, and that's what I see LLMs as being. ChatGPT
| has been a great help in debugging programs I've written in C++
| templates, both in generating the template code and trying to
| decipher errors generated, leading to suggestions for the
| template code rather than the expanded syntax.
| aleden wrote:
| Yeah, totally. I find LLMs are very useful for doing stuff
| with the preprocessor, too. ChatGPT taught me how to use
| boost preprocessor (BOOST_PP_FOR_EACH_PRODUCT).
|
| Still though, I want to see MyMapType::value_type in compiler
| errors rather than... Well, you know. It's going to contain
| the type of the key, the type of the value, the type of the
| allocator, just when all you want to really know is that it's
| a pair<key, value>, which I think most people know of as My
| map type::value_type.
| wk_end wrote:
| Weren't concepts supposed to fix this? Apparently they made it
| into the 2020 standard. I haven't touched the language in many
| years - did they not help?
| andrewflnr wrote:
| Concepts did not actually make it into the standard. I
| vaguely recall they were cut at the last minute or something.
| suby wrote:
| Concepts are in C++20. I don't know the specifics but it's
| my understanding that the version we got is stripped down
| in comparison to the original proposal.
| andrewflnr wrote:
| Oh, woops. Maybe they I only updated my belief before
| 2020. OP is right about one thing, cppreference is great.
| https://en.cppreference.com/w/cpp/language/constraints
| ryao wrote:
| > I want you to ask yourself an honest question. When was the
| last time you actually had fun in programming?
|
| Every time I write C code.
| binary132 wrote:
| For me, C is fun until I hit a certain level of abstraction
| complexity involving fake homespun vtables and it starts
| getting harder than it should be to chase down bugs.
| NooneAtAll3 wrote:
| every time I write C code, I don't want to remember how to
| implement unordered map
| kragen wrote:
| You mean enum { nb = 1024 }; struct
| { int k, v; } hash[nb]; // 0 is an invalid key
| void incr(int k) { int i = k % nb, j = i;
| do { int k2 = hash[i].k; if (k2 && k2
| != k) { i = (i+1) % nb; continue;
| } hash[i].k = k; hash[i].v++;
| return; } while (i != j); abort();
| }
|
| Apologies for the telegraphic variable names and weird
| control flow. I wrote this on my cellphone. Lacking these 15
| lines are what keep you from writing C?
|
| There's a nice tutorial on hash tables in K&R, and I can also
| recommend learning about Chris Wellons's "MSI" hash table
| design, described in C at
| https://nullprogram.com/blog/2022/08/08/. He shows a more
| full featured hash table in about 30 lines of code, depending
| on what functionality you need. It's eminently practical, and
| usually a lot faster than generic algorithms.
|
| That's not an exceptionally simple hash table either. One
| night I hurriedly wrote a rather long-winded implementation
| also on my cellphone (strings, with separate chaining and a
| djb-style hash function) and it also came to about 30 lines
| of code: http://canonical.org/~kragen/sw/dev3/justhash.c
| uecker wrote:
| You can't use anyone else code and always delete your own
| previous implementation?
| spacechild1 wrote:
| Everytime I need to write C, I wish I could use C++ instead.
| The things I miss most are RAII, templates, lambdas, const-
| correctness, and most importantly, a standard library with
| container types and algorithms.
| uecker wrote:
| What is wrong with const-correctness in C?
|
| I think container types and algorithms is a fair point, but
| if you program C more you should have a go-to library or your
| own implementation.
| uecker wrote:
| I agree, I switched from C++ to C and I found it relaxing to be
| able to just forgot about a million language features and their
| complicated interactions.
|
| I also find you have some experience, know how to build good
| abstractions and have a set of good data structures, there is
| no issue with address complex problems in C.
| 8f2ab37a-ed6c wrote:
| Come write products on top of Unreal Engine, you will have the
| opportunity to dive into 20+ MLoC of real time C++ goodness. Make
| sure it's a multiplayer experience for bonus points, eventual
| consistency makes everything extra exciting.
|
| It gives you an appreciation of just how unlikely we're to ever
| move away from the stuff, short of an LLM innovation that can
| digest codebases of that size and do an automated port, which I
| suppose is not outside of the realm of reality these days.
| IshKebab wrote:
| There's too much wrong in this rant to list...
| ModernMech wrote:
| I think we can start with "C++ is not popular enough to attract
| the weirdos".
|
| Presumes C++ is not popular and also popularity attracts
| weirdos. If anything, weirdos are attracted to languages that
| are not popular at all. I remember once I was on a small
| language project and this guy on the mailing list wouldn't stop
| going on about how our language had to support vorpal math.
| nayuki wrote:
| > C++ Is An Absolute Blast
|
| No, it's one of the worst languages I ever used. Tons of footguns
| and bad design choices everywhere. Too much cognitive load for
| less benefit than other languages.
|
| I'm surprised the article didn't mention <iostream>. The
| f.fail(), f.eof(), f.flags() are confusing and verbose. Even
| something as simple as f.read() doesn't return the number of
| elements read, so you need to make a separate call to f.gcount().
| And then there are all the opaque types like std::streamsize,
| std::mbstate_t, etc., where you have no idea how their sizes
| relate to language types like int/long/etc. or fixed-width types
| like int32_t/uint64_t/etc.
| https://en.cppreference.com/w/cpp/string/char_traits
|
| And then there are the redundancies. int x = 0; int x(0); int
| x{0}; all roughly do the same things but have subtle differences
| in more advanced use cases. This recent thread (
| https://codereview.stackexchange.com/questions/294784/c20-ro... )
| reminded me that `typedef` got replaced by `using`. A while ago,
| I came up with a long list of near-duplicate features:
| https://www.nayuki.io/page/near-duplicate-features-of-cplusp...
|
| > JavaScript still can't even figure out what a for-loop is
|
| ECMAScript 6 added the for-of loop, which is the more useful
| alternative to the for-in loop.
|
| > C++ has lambda, and it's not bullshit like Python's lambda
|
| C++ lambdas have a heavier syntax than any other lambda I know of
| (e.g. Python, Java, JavaScript, Haskell, Rust), because it needs
| to specify attributes and captures.
| https://en.cppreference.com/w/cpp/language/lambda
|
| > My thinking is C++ is now about as good as any other language
| out there
|
| Not by a longshot. Instead of C++, I reach for Java if I want
| fast design time, safe operations, and a more limited set of
| tools (e.g. not needing to decide how many layers of pointer
| indirection I want). I reach for Rust if I want the power of C++
| without its footguns.
|
| Heck, my motto for Rust has always been, "C++ done right". Every
| time I compare analogous features in C++ and Rust, I find that
| the Rust version is much better designed. As the simplest
| example, in Rust it's a compile-time error to use a variable
| whose value is moved out, whereas in C++ the variable is still
| usable but has an invalid value. Another example is that Rust has
| traits but C++ relies on instantiating templates and then "duck-
| typing" to see if the resulting code can actually compile. And
| let's not forget nullptr, the trillion-dollar mistake - C++ makes
| nullptr implicitly part of every pointer(*) type, but Rust bans
| it by default unless you opt in with Option<T>. Rust has other
| quality-of-life features such as easily declared tuple types, the
| unit type instead of void (which makes functional programming
| easier as you don't have to special-case void), pattern matching
| and unpacking, methods on primitive types (e.g. 456u32.isqrt()
| instead of sqrt(456)). I just can't look at C++ seriously when
| Rust is miles ahead, being more expressive and safer.
|
| > The Amazing Comeback of C++11
|
| I will agree with this in a limited sense When I write C++ code
| (because I'm a masochist), I will not tolerate anything less than
| C++11, because C++03 and C++98 are much, much worse. I'm talking
| about things like various types, standard library
| classes/functions, unique_ptr, and move semantics.
| motorest wrote:
| > No, it's one of the worst languages I ever used.
|
| That says more about you than the languages you've used.
|
| C++ is one of the top 5 languages used in production. This is
| true still today, with so many specialized languages to pick
| and choose. No one had to hold a gun to anyone's head to get
| them to adopt it. How do you rationalize that if your opinion
| had any substance or merit?
|
| For the sake of argument, I assert exactly the opposite: C++
| post-C++11 is the absolute best language ever devised by
| mankind, bar none. Am I wrong?
|
| > Tons of footguns and bad design choices everywhere.
|
| Please go ahead and point out the single most egregious "foot
| gun" or bad design choice you can possibly imagine. The worst.
| This will serve to show the world how well thought through your
| opinion actually is.
| whytevuhuni wrote:
| I don't think C++ is one of the worst languages; there are
| very few languages as powerful as C++, that alone makes it
| one of the best.
|
| But, much like love and hate, I also don't think that the
| opposite of good is always necessarily bad, nor vice-versa. A
| language can be both good and bad at the same time, in
| different aspects.
|
| C++ is really good (unrestrained freedom, performance,
| ecosystem), and also really bad (tooling, templates, really
| hard to debug memory issues).
|
| Rust is somewhat less good (less free, slower, puny ecosystem
| in comparison), but also a _lot_ less bad (powerful type
| system, thread safety, fearless iterators /lambdas, etc).
|
| Many of the warts C++ has to carry due to its commitment to
| compatibility, are fixed in Rust with much better
| alternatives. A lot of footguns are well encapsulated in
| Rust's affine-ish types and algebraic data types, while still
| providing unsafe hatches for when you need them. Defaults
| really matter.
| wiseowise wrote:
| > No one had to hold a gun to anyone's head to get them to
| adopt it. How do you rationalize that if your opinion had any
| substance or merit?
|
| We did. It was either C or C++ that were supported by our
| hardware vendor.
|
| > For the sake of argument, I assert exactly the opposite:
| C++ post-C++11 is the absolute best language ever devised by
| mankind, bar none. Am I wrong?
|
| Absolutely. It is one of the most complex and error prone
| languages out there.
| sunshowers wrote:
| Lambdas that can borrow from the stack and still return.
| Absolutely unacceptable feature without a borrow checker.
| jandrewrogers wrote:
| > in Rust it's a compile-time error to use a variable whose
| value is moved out, whereas in C++ the variable is still usable
| but has an invalid value
|
| C++ does it this way because there are common cases in systems
| code where doing it the Rust way would literally be unsafe. Not
| all memory references are visible at compile-time and may exist
| outside the address space.
| aw1621107 wrote:
| Would you mind elaborating more on those common cases? I'm
| not sure I've heard of destructive moves being less safe than
| non-destructive moves and I'm not smart enough to figure out
| what you're talking about in your second sentence.
| jandrewrogers wrote:
| Shared address space. Some other process or silicon can
| read or write the object you just moved but doesn't know
| you moved it. You need to keep the memory previously
| occupied by the moved object valid long enough for those
| references to realize you moved it to prevent corruption.
|
| A typical case is high-performance I/O, which uses a lot of
| DMA. DMA is oblivious to most programming language
| semantics like lifetimes, ownership, etc and will happily
| step all over your address space if you aren't careful.
| sunshowers wrote:
| This just means that affine types aren't the right tool
| to model memory that you don't have full control over.
| Which is true, but also represents a very small subset of
| overall data. Rust provides you with other tools to
| handle those kinds of situations.
|
| There is a small wart here, which is that (with async
| Rust) some of these use cases would benefit tremendously
| from full-fledged linear types, or at least an easy way
| to run code during async cancellation.
|
| The difference between an affine and a linear type is
| that the ways in which a linear type is consumed are
| controllable through encapsulation -- for example,
| imagine you have a type which represents a certain amount
| of money, and you want to statically prevent the money
| from being dropped on the floor. Affine types don't
| prevent that statically, but linear types do. You can
| still have runtime checks though.
| the__alchemist wrote:
| I'm curious to hear more about this use case. The DMA I
| do in rust is generally static buffers, because I'm not
| sure how to pass the borrow checker otherwise. (There are
| ways). Generally, you set up a static [u8] buffer, and
| pass its pointer to the hardware that's doing the DMAing.
| Then magic, then the buffer gets read or written by the
| hardware. In this scenario, the variables never go out of
| scope. Am I cheating, and avoiding this issue by using
| static buffers? If the buffer drops during a DMA
| transfer, I believe UB happens.
|
| I'm suspicious a similar principle happens with memory-
| mapped flash memory as well, e.g. QSPI.
| aw1621107 wrote:
| Thanks for taking the time to elaborate!
|
| > Some other process or silicon can read or write the
| object you just moved but doesn't know you moved it.
|
| That should primarily affect buffers that are inline with
| the moved object, right? i.e., not static buffers or
| stuff that's heap-allocated? How common is that scenario?
| I admittedly generally thought DMA used static buffers,
| though to be fair I'm not exactly highly experienced in
| the space.
|
| > You need to keep the memory previously occupied by the
| moved object valid long enough for those references to
| realize you moved it to prevent corruption.
|
| How is this (reliably) handled in C++? I feel there's
| gotta be more than just hoping the empty object hangs out
| long enough for the rest of the system to catch on (e.g.,
| moving things around near the end of a scope when the
| empty object will be destroyed "soon").
| zahlman wrote:
| I'm mostly very much in agreement with what you've said here
| but I want to pick on a few things:
|
| > Instead of C++, I reach for Java if I want fast design time,
| safe operations, and a more limited set of tools (e.g. not
| needing to decide how many layers of pointer indirection I
| want).
|
| I don't think I've ever seen a good reason to prefer Java over
| C# for anything.
|
| > Another example is that Rust has traits but C++ relies on
| instantiating templates and then "duck-typing" to see if the
| resulting code can actually compile
|
| Is the https://en.cppreference.com/w/cpp/header/type_traits
| functionality not sufficient for what you have in mind?
|
| >the unit type instead of void (which makes functional
| programming easier as you don't have to special-case void)
|
| Why would special-casing be necessary? You don't need to say
| e.g. that mapping a void-returning function produces an empty
| result; it could just be a compile error. I feel like void
| returns _should be_ a special case and I don 't like all the
| ways `None` is used in Python, because it's one of the few
| things that blurs an otherwise very strong distinction between
| statements and expressions, analogously between commands and
| queries.
| xonre wrote:
| You are correct wrt to iostream, it's bad. I stick to studio.h.
| halfcat wrote:
| I recall not being very effective with C++ for years, and then
| someone recommended the book Large Scale C++ Software Design, and
| that was a big unlock.
|
| I didn't use 80% of what's in the book, but just having a
| comprehensive way of structuring the code was a massive
| productivity boost. Looking back, I suspect it was less that it
| was "the right way", but just that it was "a way" and most of the
| benefit was it kept me from overthinking and got me to work.
|
| Later with C++11, I kept having this thought, "in Python this
| would be way less verbose", and I started writing C++ that looked
| more like Python, creating whatever helper functions Python would
| have (mostly simple stuff, string handling, etc).
|
| That was one of the most productive seasons of programming I ever
| had, and I still get tempted to write stuff in C++ that Python is
| better suited for, just because the benefit of not overthinking
| is that significant (at least for me).
| andai wrote:
| >But, C++ kept evolving, and the standards committee seemed to
| realize that if they don't do something they'll become an obscure
| language only used by a single 10 trillion dollar industry. How
| pathetic!
|
| Which industry is this referring to?
| brabel wrote:
| My guess is that it's the game industry, because it's probably
| worth that much and is almost pure C++.
| ajuc wrote:
| The stuff you use for work is not fun. The stuff you use for fun
| is fun. There, I solved the mystery for you.
|
| If you choose technology for work by what is the most fun - you
| enter a hedonist treadmill. Stop. JS framework insanity lies that
| way. No cool technology will save you from burnout.
| derriz wrote:
| I was C++ dev for 5 or 6 years, up to the late 2000s.
|
| I got another C++ job about 3 years ago but bailed after about a
| year.
|
| I could write a tome about what I dislike but to start with, any
| language that lacks a working standard built-in string type, is
| just a hard no for me at this stage in my life. Life is just too
| short.
|
| The tooling and IDE support is atrocious, no standard dependency
| management for 3rd party libraries and CMake makes maven look
| well designed.
|
| I tried to pull my knowledge up to date. Hmmm, we used to have
| lvalues and rvalues, what's this prvalue thing?
|
| Surely cppreference can explain:
|
| > _a prvalue ("pure" rvalue) is an expression whose evaluation_
|
| > _- computes the value of an operand of a built-in operator
| (such prvalue has no result object), or_
|
| > _- initializes an object (such prvalue is said to have a result
| object)._
|
| > * The result object may be a variable, an object created by
| new-expression, a temporary created by temporary materialization,
| or a member thereof. Note that non-void discarded expressions
| have a result object (the materialized temporary). Also, every
| class and array prvalue has a result object except when it is the
| operand of decltype;*
|
| > _The following expressions are prvalue expressions:_
|
| > _a literal (except for string literal), such as 42, true or
| nullptr;_
|
| > _a function call or an overloaded operator expression, whose
| return type is non-reference, such as str.substr(1, 2), str1 +
| str2, or it++;_
|
| > _a++ and a--, the built-in post-increment and post-decrement
| expressions;_
|
| > _a + b, a % b, a & b, a << b, and all other built-in arithmetic
| expressions;_
|
| > _a && b, a || b, !a, the built-in logical expressions;_
|
| > _a < b, a == b, a >= b, and all other built-in comparison
| expressions;_
|
| > _& a, the built-in address-of expression;_
|
| > _a.m, the member of object expression, where m is a member
| enumerator or a non-static member function[2];_
|
| > _p- >m, the built-in member of pointer expression, where m is a
| member enumerator or a non-static member function[2];_
|
| > _a.*mp, the pointer to member of object expression, where mp is
| a pointer to member function[2];_
|
| > _p- >*mp, the built-in pointer to member of pointer expression,
| where mp is a pointer to member function[2];_
|
| > _a, b, the built-in comma expression, where b is an prvalue;_
|
| > _a ? b : c, the ternary conditional expression for certain b
| and c (see definition for detail);_
|
| > _a cast expression to non-reference type, such as static_cast
| <double>(x), std::string{}, or (int)42;_
|
| > _the this pointer;_
|
| > _an enumerator;_
|
| > _a non-type template parameter of a scalar type;_
|
| > _a lambda expression, such as [](int x){ return x * x; };_
|
| > _(since C++11)_
|
| > _a requires-expression, such as requires (T i) { typename
| T::type; };_
|
| > _a specialization of a concept, such as
| std::equality_comparable <int>._
|
| > _(since C++20)_
|
| > _Properties:_
|
| > _Same as rvalue (below)._
|
| > _A prvalue cannot be polymorphic: the dynamic type of the
| object it denotes is always the type of the expression._
|
| > _A non-class non-array prvalue cannot be cv-qualified, unless
| it is materialized in order to be bound to a reference to a cv-
| qualified type(since C++17). (Note: a function call or cast
| expression may result in a prvalue of non-class cv-qualified
| type, but the cv-qualifier is generally immediately stripped
| out.)_
|
| > _A prvalue cannot have incomplete type (except for type void,
| see below, or when used in decltype specifier)._
|
| > _A prvalue cannot have abstract class type or an array
| thereof._
|
| Yeah, this language is loads of fun. I've worked on compilers,
| interpreters, implemented extended Hindley-Milner type systems,
| etc. so normally love reading formal language specs but this is
| just insane.
| AnimalMuppet wrote:
| > any language that lacks a working standard built-in string
| type, is just a hard no for me at this stage in my life.
|
| Um, std::string is a thing...
| TrianguloY wrote:
| I've had a similar situation with Kotlin. I've always been a java
| developer, and I enjoy using it, but even with the newer features
| it's just...slow.
|
| When I had to script things I chose JavaScript (native
| JavaScript) since it's way faster to iterate, but I've always
| missed the static typing (I also know python, but I honestly
| prefer JavaScript)
|
| Until I learned Kotlin. It's been a blast to use, incredible
| common libraries, streams everywhere, nulls that you can use
| without issues...I just love it (so much in fact that I'm in the
| process of switching project from java to Kotlin).
|
| When I need to do scripts, like for the advent-of-code, I choose
| Kotlin.
| adra wrote:
| I also really enjoyed the jump into Kotlin as well! That said,
| I'm also very happy with recent java versions trying very hard
| to close the gap. It does feel like at least half of Java's
| recent major lifts have been to emulate things done well in
| other languages (a great attribute for a self-aware language
| developer). I definitely never appreciated a lot of their newer
| feature choises like records until I saw them working really
| well in Kotlin data classes.
| shmerl wrote:
| C++ is fun, but "Rust weirdos" are right. Don't use C++, use
| Rust. That's all.
| wiseowise wrote:
| > Need package management? Check out Conan, Meson's WrapDB, and
| vcpkg.
|
| No, just no. All of them are complete, utter crap that doesn't
| hold a candle to languages that were designed with packages in
| mind. We're using Conan at work, I've been using vcpkg at home
| and I loathe both.
|
| > I mean, do you really think Python's package management is top
| notch? You do? Why are there like 10 package managers then?
|
| Worst Python package manager runs circles around whatever C++
| offers.
| synergy20 wrote:
| what's wrong with vcpkg? looks good to me
| Philpax wrote:
| I don't think we need to pretend Python package management is
| good to contrast C++, they're both awful for different reasons.
|
| At least there's maybe a way out for Python (uv / the various
| PIPs); C++ doesn't appear to have any kind of plan whatsoever,
| outside of gesturing in the direction of modules.
| amelius wrote:
| Is anyone still using the Boost libraries?
| spacechild1 wrote:
| Yes! Boost.Asio is still the go-to networking library. (It's
| also available as a standalone, though.)
|
| Some parts have been adopted by the C++ standard library and
| can thus be considered obsolete, there a still quite a few
| goodies!
| nurumaik wrote:
| Yes, it gives me free coffee breaks every time I compile my
| code
| ironman1478 wrote:
| C++ really is a blast and I think the complaints people have
| about it really depend on context. Lots of C++ devs hate that
| language but imo misdirect their hate. They actually work on
| legacy products built by people who were never that great at
| writing software. This happened to me with Rust actually where I
| was thrust into an existing rust project at the company I work
| for. It's an "old" codebase with many different and conflicting
| conventions within it (different error handling types that don't
| compose well, bad class abstractions, lots of unsafe block when
| not needed, etc). The project was the most miserable project I've
| ever worked on and it's easy for me to blame Rust, but it's
| really just bad software development. There are warts in C++, but
| a lot of the pain people run into is just that they are working
| on crap code and it would be crap in any language.
| psyclobe wrote:
| This 1000%, stop blaming the tools!
| mrcsd wrote:
| How can we make better tools if we don't blame tools?
| zdragnar wrote:
| Eh, I'm reminded of the old "programming languages as
| weapons" comic, with the one that I still remember is
| JavaScript was a sword without a hilt, with the blade being
| the "good part" and in place of the hilt, another blade
| labelled the "bad part".
|
| You can blame devs instead of tools all day long, but you
| can't deny that there are things about the tools that hold
| the developers back.
| nvarsj wrote:
| True - but it's much easier to make an incomprehensible mess in
| more complex languages. Whereas blub language projects are
| pretty easy to decipher regardless of the state of the
| codebase.
| zahlman wrote:
| I really can't resonate with this. The type system is obnoxious
| (and you don't even get proper memory safety out of it), the
| "most vexing parse" truly is vexatious, there's all the
| weirdness inherited from C like pointer decay (and then
| building new solutions like std::array on top while being
| unable to get rid of old ways of doing things), and of course
| the continued reliance on a preprocessor to simulate an actual
| module import system (and the corresponding implications for
| how code for a class is organized, having to hack around with
| the pimpl idiom etc....)
|
| Essentially, the warts are too large and numerous for me to
| find any inner beauty in it any more.
| ironman1478 wrote:
| I mean, this is all anecdotal, but I've only ran into the
| most vexing parse a few times, I rarely had to use the pimpl
| idiom, and the header file stuff... okay that isn't great.
| I've been a c++ dev for 10 years and I actually worked on an
| extremely old codebase and was involved in modernizing it is
| to C++11. Maybe I'm too C++ brained, but all those things
| just aren't that bad? There is no wartless language and you
| just deal with the warts of the language you're in and it's
| your responsibility to learn the details of the language.
| blep-arsh wrote:
| I can deal with all the warts but I'm not really having a
| blast.
| cataphract wrote:
| The header stuff is pretty bad. The rest are strange
| choices of stuff to complain about. The vexing parse was
| never a big deal and these days with bracket initialization
| (which only rarely you can't use) even less. The pimpl
| idiom: not sure why it's really a problem. Plus you have
| many choices for type erasure in c++.
| zahlman wrote:
| >The vexing parse was never a big deal
|
| I definitely got bit by it multiple times.
|
| >The pimpl idiom: not sure why it's really a problem.
|
| Because it's even more boilerplate and adds indirection
| in a place where you might have been painstakingly trying
| to avoid it (where the first indirection costs you all
| your cache coherency). C++ lets you go out of your way to
| avoid objects having to carry any overhead for virtual
| dispatch if you aren't going to use it; but then you
| might have to choose between rerouting everything through
| a smart pointer _anyway_ or suffering inordinately long
| compile times. Nothing to do with type erasure (if I 'm
| thinking clearly, anyway).
| delta_p_delta_x wrote:
| > and of course the continued reliance on a preprocessor to
| simulate an actual module import system
|
| C++ modules are supposedly meant to save the day. Although
| only recently have the big three compilers (GCC, Clang, MSVC)
| reached some form of parity when compiling modules.
| CJefferson wrote:
| In every other language (except C), basically every time you
| write v[x]=y you aren't inviting the possibility of arbitary
| memory corruption. The C++ 'std::optional' type makes calling
| '*v' undefined behaviour if 'v' is empty. The whole point of
| optional is to store things that might be empty, so why put
| undefined behaviour on the most common operation on an optional
| when it's empty (which is going to be common in practice,
| that's the point!)
|
| The problem I have with C++ (and I've written a lot), is every
| programmer involved in your project has to be 100% perfect,
| 100% of the time.
|
| I know you can run memory checkers, and STL debug modes, but
| unless you are running these in release as well (is anyone
| doing that?), then you are then counting on your testsuite
| hitting every weird thing a silly, or malicious, user might do.
|
| Given how important software is nowadays, and how Rust seems
| close to the performance of C++, is it really worth using a
| language where so many of the basic fundamental features are
| incredibly hard to use safely? They keep making it worse,
| calling an empty std::function threw an assert, the new
| std::copyable_function has made this undefined behaviour
| instead!
| CyberDildonics wrote:
| _The C++ 'std::optional' type makes calling '_v' undefined
| behaviour if 'v' is empty*
|
| Are you talking about dereferencing a null pointer? That is
| going to case a low level exception in any language, it has
| nothing to do with std::optional.
|
| _every time you write v[x]=y you aren 't inviting the
| possibility of arbitary memory corruption_
|
| That's how computers work. You either pay the penalty of
| turning every memory check into a conditional boundary check
| first or you avoid it all together and just iterate through
| data structures, which is not difficult to do.
|
| Also debug mode lets you turn on the bounds checking to debug
| and be fast in release mode.
|
| The reality is that with a tiny amount of experience this is
| almost never a problem. Things like this are mostly relegated
| to writing your own data structures.
| CJefferson wrote:
| No, I'm talking about std::optional<T>. It's a type
| designed to store an object of type T, or nothing. You use
| '*v' to get the value out (if one is present).
|
| It was originally discussed as a way of avoid null
| pointers, for the common case where they are representing
| the possibility of having a value. However, it has exactly
| the same UB problems as a null pointer, so isn't really any
| safer.
|
| I'm going to be honest, saying that memory corruption in
| C++ is 'almost never a problem' just doesn't match with my
| experience, of working on many large codebases, games, and
| seeing remote security holes caused by buffer overflows and
| memory corruption occurring in every OS and large software
| program ever written.
|
| Also, that 'penalty' really does seem to be tiny, as far as
| I can tell. Rust pays it (you can use unsafe to disable it,
| but most programs use unsafe very sparingly), and as far as
| I've seen benchmarks, the introduced overhead is tiny, a
| couple of percent at most.
| CyberDildonics wrote:
| _It was originally discussed as a way of avoid null
| pointers,_
|
| I don't think this is true. I don't think it has anything
| to do with null pointers, it is a standard way to return
| a type that might not be constructed/valid.
|
| I think you might be confusing the fact that you can
| convert std::optional to a bool and do if(opt){
| opt.value(); }
|
| You might also be confusing it for the technique of
| passing an address into a function that takes a pointer
| as an argument, where the function can check the pointer
| for being null before it puts a value into the pointer's
| address.
|
| _I 'm going to be honest, saying that memory corruption
| in C++ is 'almost never a problem' just doesn't match
| with my experience,_
|
| In modern C++ it is easy to avoid putting yourself in
| situations where you are calculating arbitrary indices
| outside of data structures. Whether people do this is
| another story. It would (or should) crash your program in
| any other language anyway.
|
| _Also, that 'penalty' really does seem to be tiny_
|
| The penalty is not tiny unless it is elided all together,
| which would happen in the same iteration scenarios that
| in C++ wouldn't be doing raw indexes anyway.
| Maxatar wrote:
| >I don't think this is true. I don't think it has
| anything to do with null pointers
|
| The paper that proposed std::optional literally uses
| examples involving null pointers as one of the use cases
| that std::optional is intended to replace:
|
| https://isocpp.org/files/papers/N3672.html
|
| Here is an updated paper which is intended to fix some
| flaws with std::optional and literally mentions
| additional use cases of nullptr that the original
| proposal did not address but the extended proposal does:
|
| https://www.open-
| std.org/jtc1/sc22/wg21/docs/papers/2023/p29...
|
| I am going to be somewhat blunt, but if you're not
| familiar with how some of the use cases for std::optional
| is as a replacement for using raw pointers, along with
| some of your comments about how C++ treats undefined
| behavior, as if it's just results in an exception,
| suggests you may not have a rigorous enough understanding
| of the language to speak so assertively about the topic.
| CyberDildonics wrote:
| _I am going to be somewhat blunt, but if you 're not
| familiar with how some of the use cases for std::optional
| is as a replacement for using raw pointers_
|
| I never said there wasn't a use case, I said it wasn't
| specifically about protecting you from them. If you put a
| null pointer in and reference the value directly, it
| doesn't save you.
|
| If you don't understand the context of the thread start
| arguments over other people's simplified examples. I'm
| not going to write huge paragraphs to try to avoid
| someone's off topic criticisms, I'm just telling someone
| their problems can be avoided.
| Maxatar wrote:
| Yes you did and I literally quoted it, here it is, your
| words:
|
| "I don't think this is true. I don't think _it has
| anything to do with null pointers_ , it is a standard way
| to return a type that might not be constructed/valid."
|
| This was in response to:
|
| "It was originally discussed as a way of avoid null
| pointers,"
|
| I have provided you with the actual papers that proposed
| std::optional<T> and they clearly specify that a use case
| is to eliminate the use of null pointers as sentinel
| values.
| CyberDildonics wrote:
| It's a template, you can put whatever you want in it
| including a pointer. All your example shows is that you
| can bind a pointer to a reference and it will wrap it but
| won't access the pointer automatically.
|
| I'm not sure what your point here is other than to try to
| mince words and argue. It's a standard way to put two
| values together and what people were probably already
| doing with structs. You can put pointers into a vector
| too, but that doesn't mean it's all about pointers.
| Maxatar wrote:
| It's okay to admit you were wrong.
| CyberDildonics wrote:
| I think if you had something real to say here you would
| have done it already.
| saghm wrote:
| I'm pretty sure the issue that the parent commenter is
| referring to isn't about wrapping a pointer type in an
| optional, but wrapping a _non-pointer_ type in an
| optional, and then trying to access the value inside.
| std::optional literally provides a dereference operator
| operator[1] which contains the following documentation:
|
| > The behavior is undefined if _this does not contain a
| value.
|
| The equivalent to this in Rust isn't `Option::unwrap`,
| which will (safely) panic if the value isn't present; the
| equivalent is `Option::unwrap_unchecked`, which can't be
| invoked without manually marking the code as unsafe. I've
| been writing Rust professionally for a bit over five
| years and personally for almost ten, and I can
| definitively say that I've never used that method a
| single time. I can't say with any amount of certainty
| whether I've accidentally used the deference operator on
| an optional type in C++ despite writing at least a couple
| orders of magnitude less C++ code because it's not
| something that's going to stick out; the deference
| operator gets used quite often and wouldn't necessarily
| be noticeable on a variable that wasn't declared nearby,
| and the compiler isn't going to complain because it's
| considered entirely valid to do that.
|
| [1]: From https://en.cppreference.com/w/cpp/utility/optio
| nal/operator_
| jpc0 wrote:
| Is your argument that rust with panic if you are a bad
| programmer and C++ says its Ub of you are a bad
| programmer?
|
| That's just fundamental difference of opinion, Rust isn't
| designed for efficiency, it's designed for safety first.
| C++ unofficial motto is, don't pay for what you don't
| use.
|
| If I type *X why would I pay for a check if its empty, I
| literally should have checked the value isn't empty.
|
| If you work in a code base with people who don't check,
| your codebase doesn't have static analysers, you do no
| code review and dereferencing an uncheck optional get's
| to production, do you think a .unwrap in rust wouldn't
| have made it to production?
| CJefferson wrote:
| Your basis seems to be no-one is ever going to write bad
| code, anywhere, ever, and invoke undefined behavior. That
| doesn't seem reasonable.
|
| Also, an unwrap isn't perfect, but it's much better than
| UB. It asserts. No memory corruption, no leaking all your
| user's data, no massive fines.
|
| The equivalent to C++ would be an unchecked unwrap in an
| unsafe code block, and that would throw up flags during
| review in any Rust codebase.
| jpc0 wrote:
| An unchecked dereference should also throw up flags
| during review in a C/C++ codebase. I didn't assume that
| nobody would make mistakes. My argument has always been
| that you use a language like C++ where needed. Most of
| your code should be in a GC language. Going in with that
| mentality, even if I wrote that code in Rust, I'm
| exporting a C API, which means I may as well have written
| the code in C++ and spend some more time in code review.
|
| EDIT: an unwrap that crashes in a panic is a dos
| condition. In severity this might be worse or better
| depending where it happens.
|
| Both are programmer error, both should be caught in
| review, both aren't checked by the compiler.
| jodrellblank wrote:
| > " _Rust isn 't designed for efficiency"_
|
| Citation needed, because Graydon Hoare the original Rust
| creator (who has not been involved with Rust development
| for quite a long time) wrote about how the Rust that
| exists is not like the original one he was designing:
|
| - "Tail calls [..] I got argued into not having them
| because the project in general got argued into the
| position of "compete to win with C++ on performance" and
| so I wound up writing a sad post rejecting them which is
| one of the saddest things ever written on the subject. It
| remains true with Rust's priorities today"
|
| - "Performance: A lot of people in the Rust community
| think "zero cost abstraction" is a core promise of the
| language. I would never have pitched this and still,
| personally, don't think it's good. It's a C++ idea and
| one that I think unnecessarily constrains the design
| space. I think most abstractions come with costs and
| tradeoffs, and I would have traded lots and lots of small
| constant performancee costs for simpler or more robust
| versions of many abstractions. The resulting language
| would have been slower. It would have stayed in the
| "compiled PLs with decent memory access patterns" niche
| of the PL shootout, but probably be at best somewhere in
| the band of the results holding Ada and Pascal."
|
| https://graydon2.dreamwidth.org/307291.html
| jpc0 wrote:
| The fact that by default array access is bounds checked
| in Rust and by default it isn't in C++ disproves that.
|
| I think you would have a hard time convincing the C++
| standards committee to put a checked container in the
| standard, maybe now with the negative publicity maybe but
| definitely not before.
|
| I'm guessing it would be impossible to get an unchecked
| container into the rust stdlib.
| CJefferson wrote:
| I just want to pick out one thing:
|
| _It would (or should) crash your program in any other
| language anyway._
|
| To me there is a massive difference between "there is a
| way a malicious user can trigger an assert, which will
| crash your server / webbrowser", and "there is a way a
| malicious user can use memory corruption to take over
| your server / webbrowser".
|
| And bounds-checking penalties are small. I can tell they
| are small, because Rust doesn't have any kind of clever
| 'global way' of getting rid of them, and I've only
| noticed the cost showing up in profiles twice. In those
| cases I did very carefully verify my code, then turn off
| the bounds checking -- but that's fine, I'm not saying we
| should never bounds check, just we should do it by
| default. Do you have any evidence the costs are
| expensive?
| CyberDildonics wrote:
| If you profile looping through an array of pixels in
| linear memory order vs bounds checking every access it
| should be more expensive due to the branching.
|
| As someone else mentioned you can boundary check access
| if you want to in C++ anyway and it's built in to a
| vector.
|
| My point here is that it isn't really a big problem with
| C++, you can get what you want.
| Maxatar wrote:
| Iterating over an array in Rust does not involve bounds
| checking every access since Rust guarantees immutability
| to the container over the course of the iteration. Hence
| all that's needed is to access the size of the array at
| the start of the iteration and then it is safe to iterate
| over the entire array.
|
| Note that this is not something C++ is able to do, and
| C++ has notoriously subtle iterator invalidation rules as
| a consequence.
| CyberDildonics wrote:
| They asked for evidence of bounds checks being expensive,
| please try to keep the context in mind.
|
| _Note that this is not something C++ is able to do_
|
| Or you could just not mutate the container.
| Maxatar wrote:
| It's the optimization that C++ is unable to perform, not
| the immutability.
| pptr wrote:
| If you declare using an invalidated iterator as UB, the
| compiler can optimize as if the container was effectively
| immutable during the loop.
| CyberDildonics wrote:
| Are you talking about optimizing out bounds checking that
| isn't happening in the first place?
| jodrellblank wrote:
| > " _They asked for evidence of bounds checks being
| expensive_ "
|
| They said "bounds-checking penalties are small" not that
| it was free. You've described a situation where bounds
| checking happens and declared that it "should be"
| expensive because it happens. You haven't given evidence
| that it's expensive.
| carom wrote:
| You have to do a very similar operation to has_value()
| .value() with Rust's optional though... How is
| opt.ok_or("Value not found.")?; so different from the C++
| type?
| Maxatar wrote:
| One is undefined behavior which may manifest as entirely
| unpredictable side-effects. The other has semantics that
| are well specified and predictable. Also while what you
| wrote is technically valid, it's not really idiomatic to
| write it the way you did in Rust, you usually write it
| as: if let Some(value) = some_optional
| { }
|
| At which point value is the "dereferenced" value. Or you
| can take it by reference if you don't want to consume the
| value.
| carom wrote:
| I prefer ok_or for optionals and map_err for for results
| in Rust. I believe the way you proposed ends up with very
| deeply nested code which I try to avoid.
| Kranar wrote:
| It seems like people think dereferencing an unengaged
| optional results in a crash or exception, but ironically
| you are actually less likely to get a crash from an
| optional than you would from dereferencing an invalid
| pointer. This snippet of code, for example, is not going
| to cause a crash in most cases, it will simply return a
| garbage and unpredictable value: auto v
| = std::optional<int>(); std::cout << *v <<
| std::endl;
|
| While both are undefined behavior, you are actually more
| likely to get a predictable crash from the below code
| than the above: int* v = nullptr;
| std::cout << *v << std::endl;
|
| I leave it to the reader to reflect on the absurdity of
| this.
| carom wrote:
| I understand what undefined behavior is, I just don't
| dereference pointers or optionals without first checking
| them against nullptr or nullopt (respectively). In fact,
| I generally use the .has_value() and .value() interface
| on the optional which, to my point in the above comment,
| is a very similar workflow to using an optional in Rust.
|
| I think if you adopted a more defensive programming style
| where you check your values before dereferencing them,
| handle all your error cases, you might find C++ is not so
| scary. I would also recommend not using auto as it makes
| the types less clear.
| std::optional<int> v = std::nullopt; if (v ==
| std::nullopt) { return
| std::unexpected("Optional is empty."); }
| std::println("{}", *v);
|
| If you are dereferencing things without checking that
| they can be dereferenced I don't know what to tell you.
| d0mine wrote:
| What is the desired behavior? I see at least 3 options:
| panic (abort at runtime predictably), compiler error
| (force handling both Some&Nothing cases [needs language
| support otherwise annoying], exceptions (annoying to
| handle properly). There is too much undefined behavior
| already.
|
| Perhaps, 3 types could exist for 3 options.
| tangus wrote:
| You can pay the penalty and get safe container access,
| too. AFAIK, C++ standard containers provide both bounds
| checked (.at()) and unchecked ([]) element retrieval.
| CJefferson wrote:
| Now we are getting down to a philosophical issue (but I
| think an important one).
|
| In Rust, they made the safe way of writing things easy
| (just write v[x]), and the unsafe one hard (wrap your
| code in 'unsafe'). C++ is the opposite, it's always more
| code, and less standard (I don't think I've seen a single
| C++ tutorial, or book, use .at() as standard rather than
| []), to do bounds checked.
|
| So, you can write safe code in both, and unsafe code in
| both, but they clearly have a default they push you
| towards. While I think C++'s was fine 20 years ago, I
| feel nowadays languages should push developers to write
| safer code wherever possible, and while sometimes you
| need an escape hatch (I've used unsafe in a very hot
| inner loop in Rust a couple of times), safer defaults are
| better.
| Gibbon1 wrote:
| I've been wondering how much you'd pay if you just
| required that out of bounds accesses be a no-op with an
| option of calling an error handler. De-reference a null
| or out of bounds pointer you get zero. Write out of
| bounds, does nothing. int a = v[-100]; //
| yolo a is set to 0
|
| I really suspect that unlike the RISC mental model
| compiler writers think in terms of a superscalar
| processor would barely be slowed down. That is if the
| compiler doesn't delete the checks because it can prove
| they aren't needed.
| wkyleg wrote:
| I learned C++ and enjoyed it but never went too deep. I always
| enjoyed C more. There's also so many S tier codebases to read to
| learn C better like the original Dune game engine or Unix
| utilities.
|
| Having dabbled a bit with Rust recently I can't see any strong
| reasons to use C++. The combination of strong functional
| programing inspired type system with performance seems
| unbeatable. Almost a perfect language.
|
| I'm sure there must be some legacy reasons to use C++ though.
| Maybe Game Engines, embedded programing, some kind of other
| legacy tie in?
| PartiallyTyped wrote:
| HFT perhaps?
| wkyleg wrote:
| I can see that.
|
| On most metrics I've seen Rust is comparable on general
| speed.
|
| Maybe if you're at the level where you've essentially writing
| portable assembly and are okay with lack of safety. You need
| to know exactly what is happening within the CPU, maybe on
| custom hardware.
|
| I bet some defense applications would be in this category
| too, although for my own sense of self preservation I would
| prefer the Rust type system.
| gpderetta wrote:
| Rust would probably be a good fit for HFT, but as the field
| is so dominated by C++ is hard for another language to make
| inroads. Java managed to some extent.
|
| I would expect a lot of unsafe though.
| cempaka wrote:
| Ecosystem effects are definitely important to C++'s
| dominance in HFT, but it's also a domain where a lot of
| the guarantees Rust offers just aren't all that relevant.
| From a security perspective most code always runs in
| sandboxes accessible to only a select few whitelisted
| IPs. True, you don't want a segfault while you're in the
| middle of sending an order to an exchange, but most of
| those are pretty easily smoked out in simulation testing.
| fuzztester wrote:
| _Huge_ amount of legacy across many dimensions, not just apps
| written in it [1], like number of users, published and
| available knowledge / resources (books, courses, blogs,
| articles, videos, software libraries, etc.), high compatibility
| with another huge language (C), etc.
|
| This is just software industry general knowledge, for those who
| have been there for more than a few years in the field. I am
| not even a proper beginner in it, because I have never used it
| much, although I had bought, read and to some extent,
| understood some classic C++ books, including by the language
| creator (Bjarne Stroustrup [2]), Scott Meyers [3], and a few
| others, earlier. I did have a lot of experience using C for
| many years in production, though, including on a successful
| commercial product.
|
| [1] https://www.stroustrup.com/applications.html
|
| [2]:
|
| https://www.stroustrup.com
|
| https://en.m.wikipedia.org/wiki/Bjarne_Stroustrup
|
| [3] https://en.m.wikipedia.org/wiki/Scott_Meyers
| nurumaik wrote:
| C++ makes sense when you need low latency, but don't really
| care about correctness
|
| So I believe gamedev will stay on C++ the longest
|
| Game crashes with segfaults for 0.001% users? So what?
| indigoabstract wrote:
| I really love how politically incorrect this post is. And how
| honest and fresh it sounds, though quite a few have been quick to
| say how wrong he is. They could be right, but I think it misses
| the point.
|
| Yes, it's way too easy to do dumb stuff in C++, when you're tired
| or not sure what you're doing. Things like holding raw pointers
| or references to things you shouldn't like std::vector::data(),
| or questionable reinterpret casts and many other things. The
| compiler won't stop you, only your experience.
|
| But he's right about one thing at least: Programming should be
| fun!
|
| All these layers and rules and concerns about memory safety and
| security don't offer only advantages. They also have tradeoffs.
| And it's the same thing with those scrum agile ceremonies. It
| serves its purposes. But it's also the best invention ever to
| suck all the joy out of programming.
|
| I think that both C and C++ still have that fun feeling going for
| them. When you know what you want to work on and how to do it and
| you just start doing it and get into the flow. And if you're
| careful and do things right, it just works and it's a blast!
|
| That's my takeaway from the article. That feeling like you're
| talking directly to the machine, getting it to show you on screen
| what you saw in your mind, without anything else getting in your
| way. Now, that is fun!
| zahlman wrote:
| Programming should be fun. I don't think that's controversial
| or politically incorrect. (Or if it is, I don't know why.)
|
| A lot of people don't naturally have the kind of fun in C++
| that Zed describes, and it seems most people here (including
| myself) would rather talk about that.
| indigoabstract wrote:
| It's controversial because of how he makes fun about the
| people using and promoting other languages, like Rust. I
| thought it was hilarious.
|
| And in case you haven't noticed, C++ isn't seen in a good
| light anymore for some years now. There are a lot of loud
| voices saying its time has past and calling for it to be
| replaced with something newer and better.
|
| It's all subjective anyway, but I resonate with the feeling
| of fun he describes when doing projects in C++. Feeling
| productive and being protected from whole classes of bugs
| common in C++ is all well and good, but he was talking about
| programming being fun and I do not get that same feeling when
| programming in other languages.
|
| It's perfectly understandable that you don't feel the same
| way though. I hope you do when programming in your favourite
| language. Otherwise it becomes just something you do to pay
| the rent.
| zahlman wrote:
| Zed is definitely the sort of person who can make an
| uncontroversial point sound controversial, yeah. I think
| we're in violent agreement here.
| tavavex wrote:
| > It's controversial because of how he makes fun about the
| people using and promoting other languages, like Rust. I
| thought it was hilarious.
|
| But doesn't that completely ruin the point of the post? I
| agree with you that something feeling 'fun' is more
| personal, and that the criteria of what constitutes fun are
| up to the user. The author doesn't agree with that - you
| can either adopt the former point or promote the Right Way
| of having fun. Those snarky remarks made me put this blog
| into the second category. When you're so invested in your
| argument, even a fundamentally harmless post about having
| fun will get that language wars hit piece subtext.
|
| If anything, they seem more like desperate cheap shots than
| arguments. Other people, the NSA etc dislike unsafe-by-
| default code? Well, they're just authoritarian anti-fun
| ideologues! Rust users bring up some of the same criticisms
| I recall in the last paragraph? Well.. uh... that borrow
| checker, am I right?
| indigoabstract wrote:
| I think he was just making fun of people who inflate the
| importance of their language and their way too much and
| it should be taken in that spirit. There are good reasons
| why all these new languages like Rust and Zig popped up
| in the last 10 years or so and started getting traction.
| Obviously a lot of people were unhappy having C/C++ as
| their only choice for performance focused or system level
| programming. At least in the games business it still
| seems to be doing well.
|
| But to get back to the point of the article, for fun solo
| projects, when the 'mood for coding' comes over, I may be
| biased, but I think C++ is still the best. It's like when
| building a prototype. You just want to test your idea and
| see how it looks and play with it and just worry about
| bugs and program correctness later. While coding it in
| Rust you'd have to spend extra time determining the
| correct memory ownership relations and that can break the
| flow.
|
| After programming for 20 years, it doesn't come nearly as
| often as it used to, but I still get that feeling from
| time to time.
| avalys wrote:
| If you're starting a new project with a talented team that knows
| how to use modern C++ well, I agree that C++ is great! It's a
| pleasant and powerful language, delivers great performance and
| (while complicated) is straightforward to debug and optimize.
|
| I had the privilege of working on a codebase that was about 5
| years old, written to C++11 standards or later, and I thoroughly
| enjoyed it, for many of the reasons expressed in the article.
|
| If you are working on an older codebase that has evolved over
| 20-30 years, or one that has not been maintained by talented
| people, you will have a very different experience.
| creato wrote:
| > If you are working on an older codebase that has evolved over
| 20-30 years, or one that has not been maintained by talented
| people, you will have a very different experience.
|
| I'm trying to think of any other language that could fit that
| description and not also be a terrible experience. In fact, I'd
| prefer C++ to many other possibilities I can think of (C, Java,
| Fortran). The exception would be C#, but I'm not sure if it's
| old enough to fit.
| avalys wrote:
| Fair point, although I think it's true that C++ gives you
| more rope to hang yourself with, and if I had to choose, I'd
| rather maintain a crusty old codebase written in Java than
| one written in C++.
| snovv_crash wrote:
| The issue is that the JVM has started deprecating features
| which old codebase rely on.
|
| I don't work with it, but even I know about the JVM no
| longer supporting sandboxing or being able to kill threads
| programmatically.
|
| C++ doesn't have this issue because you can still deploy
| code from an old toolchain onto a modern OS.
| adra wrote:
| You can and always have been able to .destroy() threads
| in java, but doing so breaks the memory model in ways
| that make it clear that you should never do it. My guess
| is that if you're kill heavy in c++, then you've also run
| into bugs waiting on locks of threads you've now just
| murdered. That's why there's a ton of great abstractions
| for how to "kill work running somewhere else" that
| doesn't leave your application in a potentially unstable
| state.
|
| Java 9+ sure did kill off a lot of things that weren't
| particularly ideal. Most normal devs who don't write
| libraries probably can't even name a single feature
| removed (corba, script interpreters, some jmx cruft,
| etc). Most of what was culled still exists in libraries
| that could easily be added back with project imports.
| Maybe Java applets are super dead now? I don't believe
| any modern browsers still support native plugins, but
| maybe there are some niche individuals bemoaning the loss
| of java web start.
|
| As for the "can still deploy code" comment, the same
| applies to java. Look around, and sadly you see very old
| releases of java still in use today. My guess is that if
| I fired up a java 1.0 compiler and JVM today, it would
| run on my PC (poorly).
|
| Before criticising something, please consider being well
| enough informed to warrant the comment.
| jacoblambda wrote:
| So that's a fun one. C# the language people know first
| released in y2k and the 1.0 release was 2002.
|
| So it definitely is old enough to fit and it certainly has
| it's warts from age that show up in long lived projects.
| golf1052 wrote:
| I used to work on a codebase at Microsoft that was
| classified as a microservice. Pretty much entirely written
| in C# and it was about 12 years old.
| LeftHandPath wrote:
| I started my life as a dev with PHP, learning it on the job to
| set up a custom Wordpress theme with plugins for special
| datatypes (eg STCs).
|
| When I was 21, they offered to pay for my tuition so I went
| back for a CoE degree (later switching to CS). The moment I
| touched C++ - on my very first day in their "intro to
| programming" class - I fell in love. The type system,
| debugging, and ecosystem was fantastic compared to PHP 7 that I
| was using at the time. With my manager's permission, I went
| back to some of our existing intranet apps and built a
| C++-based API for them that our PHP would call over a web-
| socket, so that I could leverage the type system (and
| performance). Those systems are still in daily use, company
| wide. Maintenance hasn't been a problem. And that's despite
| running in a really weird environment (IBM Pase for i).
|
| Now, after using Rust and Axum, I'd vastly prefer the Rust
| ecosystem for creating that type of API. But C++ deserves
| credit. It really is a great language, especially if you're
| coming from web languages like (non-TS) JavaScript or PHP.
| runjake wrote:
| Can anyone recommend some good "modern" C++ books in this spirit
| (writing software for fun, not large enterprises)?
|
| Preferably for Linux and/or Windows.
| rramadass wrote:
| Not sure about what you mean by "fun" but Peter Gottschling's
| _Discovering Modern C++ An Intensive Course for Scientists,
| Engineers and Programmers_ is pretty good. For a catalog of
| shiny new C++ features Marius Bancila 's _Modern C++
| Programming Cookbook_ is comprehensive.
| chubot wrote:
| IMO the way to make C++ fun is to: 1. Build and
| run it with a shell script (because the build systems do suck)
| Dependencies may complicate this, but you can still link with
| them with a shell script And use Unix - I started with
| C++ on Windows, and that sucks (also mentioned in the article)
| 2. Turn on address sanitizer in development, which makes it
| memory safe - you get a Python-like stack trace on
| errors instead of undefined behavior
|
| Example: $ echo 'int main() { return 42; }' >
| foo.cc $ c++ -fsanitize=address -o foo foo.c &&
| ./foo; echo $? 42
|
| I use an actual editor, and unit tests, but essentially shell is
| my REPL for C++. It's easier to figure out that way.
|
| Newer features like constexpr have subtle rules, so it's easier
| to just try it (even though I've used C++ for many years). I run
| all the tests with Clang too.
|
| ---
|
| Example with ASAN: $ echo 'int main() { char
| buf[1]; buf[1] = 42; }' > error.cc
| $ c++ -fsanitize=address -o error error.cc && ./error; echo $?
| ==118199==ERROR: AddressSanitizer: stack-buffer-overflow on
| address 0x7ffcd94eb431 at pc 0x56217647520f bp 0x7ffcd94eb400 sp
| 0x7ffcd94eb3f8 WRITE of size 1 at 0x7ffcd94eb431 thread
| T0 #0 0x56217647520e in main
| (/home/andy/git/oilshell/oil/error+0x120e) #1
| 0x7f7928446249 in __libc_start_call_main
| ../sysdeps/nptl/libc_start_call_main.h:58
|
| It's not too hard to learn to read the output, and then basically
| you can go nuts like C++ is Python. For a small program, the
| edit/run cycle will be extremely fast, like Python.
|
| The silent undefined behavior is a big barrier to learning, and
| this removes most of it. (You can also pass -fsanitize=undefined
| for UBSAN, which finds other bugs, but many fewer IME)
|
| ASAN is built into compilers; you don't need to install anything.
| A bare Debian or BSD system has all this good stuff :-)
|
| (copy of lobste.rs comment)
| epolanski wrote:
| A well written blog post that makes many valid points but comes
| with a wrong assumption: that making a language creativity-
| friendly is an absolutely desirable trait.
|
| It's a desirable trait for my personal projects, where I may use
| Haskell, Ruby, Ocaml, Racket or something more exotic.
|
| At work, I'd rather use languages that are boring, with well
| defined and uncreative patterns and practices. Professionally I
| expect to not be surprised often and I want the smallest group
| cognitive load possible.
|
| Languages that breed too much creativity tend to have a rather
| short list of killer software (that kind of software that makes
| it worth learn a specific programming language).
| barbazoo wrote:
| I feel that way with Ruby vs Python sometimes.
| zahlman wrote:
| I wonder if Zed started using, or went back to, Perl after
| getting so worked up about the 2 -> 3 transition. (From what I
| can tell, he's still complaining about it, and still wrong in
| many of those complaints, and makes unsubstantiated claims in
| others.)
| bnolsen wrote:
| I worked with c++ for many years and it has lots of warts. Slow
| compilation, lack of decent build system (no cmake isn't that
| great), mistakes made in the standard library (iostreams), weak
| cross platform standard libraries were always a headache. But I
| always loved the power that <algorithm> and the like provides,
| although attaching allocators (and other template things) kind of
| sucks.
|
| When I looked at and test drove rust all I saw was heaps of
| complexity stacked up yet again. Probably didn't help that I
| smacked headlong into the Arc Mutex and lifetimes mess. I'm
| really more inclined to go for something like 'zig' which does so
| much with simple syntax (and awesome comptime) and still gets
| excellent performance.
| marssaxman wrote:
| > no cmake isn't that great
|
| Nor is cmake even really a standard: after thirty-odd years
| writing C++, I've yet to work on a project which used it!
| PittleyDunkin wrote:
| That's pretty damn impressive! How did you manage to avoid
| codebases with CMake? Or are you just saying you personally
| chose not to use it for your own?
| scotty79 wrote:
| > lack of decent build system
|
| At one point I was using gulp.js to build my small C++
| experiment.
| readyplayernull wrote:
| I returned to C++ after 20 years to program ESP32
| microcontrollers. The Arduino Framework is compiled with C++
| 21... wait, what? Well that's the value of __cplusplus = 202100L
|
| Glad to find the standard library progressed so much to make C++
| more similar to modern languages, but sometimes I wish there was
| a simpler way to access the std namespace. Any proposal to
| replace "std::" with $
| lairv wrote:
| I just spent 3 days to statically link a third party dependency
| to my C++ project, in a way that works with linux/windows/macos.
| The package wasn't available on conan/vcpkg, it was just a github
| repo with a weird combination of Makefile/cmake file. While I'm
| far from a cmake/cpp expert, this is a non-issue with most modern
| languages: you just pip install, cargo add, npm install, go get
| etc. You can read front-to-cover books about every details of C++
| semantics and it'll still be a PITA to work on real world
| projects
| 77pt77 wrote:
| The javascript toolchain for dependencies and build is as
| arcane as the sloppiest Makefile.
|
| It's amazing that we ended up with the javascript equivalente
| of autotools.
| agumonkey wrote:
| yeah, dealing with npm really made me feel like the best part
| of autotools
| dannymcgee wrote:
| Created an account just to say: I am a 10-year JavaScript
| veteran who knows the ecosystem at least as well as any sane
| person could possibly be expected to, and this is 100%
| correct. When I tell people that JS build tooling is the
| second-worst headache to C/C++ build tooling, they laugh, but
| stick a toe outside the happy path of `npm create <some-
| framework-project> && npm start` and you will know what pain
| feels like.
|
| I did get some similar vibes trying to work with Gradle and
| Maven for a project a while back, but I don't really live in
| that world so it's hard to say whether my experience was
| typical or just symptomatic of my inexperience.
| smarkov wrote:
| And it'll continue to get worse because JS devs love coming
| up with their own abstractions over everything and piling
| complexity. You don't write JS, you write TS. You don't
| write HTML, you write JSX. You don't write CSS, you write
| Tailwind. And of course, React has its own compiler as of
| recently. Now you have to figure out in what order to run
| these parsers, bundle everything together including your
| hundreds of dependencies, minimize, obfuscate, tree shake,
| and whatever else fairy dust magic you want to sprinkle on
| top. Meanwhile, the default build tool of choice changes
| about once every 2 years, and now you also have a choice of
| runtime - node vs bun vs deno. Can't wait to see what the
| next revolutionary idea would be to contribute to this
| madness.
| claytongulick wrote:
| There are those of us out there that have a beautiful
| experience with JavaScript. Vanilla JS, web components, a
| lightweight rendering library like lit-html, class props
| as reactive state...
|
| NodeJS + express + vanilla web components is the most
| graceful and productive stack I've ever used in 30+ years
| of development.
| dannymcgee wrote:
| You forgot to mention the 3 or 4 different TypeScript
| compilers!
|
| I do have to admit at least some of the pain is self-
| inflicted on my part. I _want_ those nice abstractions,
| so I will write a damn Rollup or Babel plugin if it means
| I can use Sass stylesheets in my TypeScript+JSX
| components that compile to vanilla Custom Elements (so I
| don't have to depend on a huge framework runtime).
|
| But as nice as the Babel/Rollup/Vite plugin APIs are,
| when you start doing stuff like that you then have to
| deal with all the deep-in-the-weeds bullshit that comes
| with it, like the fact that Webpack and Rollup and
| Node.js all have subtly different (and mostly poorly
| documented) module resolution rules and that they all
| differ wildly from the official ES-module spec that the
| standards committee finally shipped like 20 years too
| late, so trying to get your unit-testing framework and
| your bundle toolchain and your browser to all agree about
| how to digest the mess you've made becomes this giant
| clusterfucktastrophe that makes you question every life
| decision and formative event that led you to the moment
| you thought this might be a neat idea.
|
| But yeah just like build a React app or whatever and
| you'll probably be fine.
| singhrac wrote:
| Good luck trying to use these tools with anything other
| than the blessed path of node on the backend.
|
| The JS ecosystem absolutely has the problem of "too many
| compilers", and of course as I'm typing this there's
| someone out there writing a "one compiler to unify them
| all".
| npalli wrote:
| But to flip this around, let's say you want to use this third
| party in some other "modern" language how would this become
| better?. Clearly if someone hadn't done the work to package in
| vcpkg/conan you can expect it wouldn't exist in pip/cargo/npm
| either. So if you had a bad time in C++, you would have a
| dramatically worse time in other languages. Goes to show what
| everyone else is saying here, there are parts of historic C++
| which are in very bad shape particularly the build story.
| However, if it's in vcpkg it is exactly as easy to install as
| the other ones.
| kouteiheika wrote:
| > But to flip this around, let's say you want to use this
| third party in some other "modern" language how would this
| become better?. Clearly if someone hadn't done the work to
| package in vcpkg/conan you can expect it wouldn't exist in
| pip/cargo/npm either. So if you had a bad time in C++, you
| would have a dramatically worse time in other languages.
|
| Err, no?
|
| In case of Rust usually there is really no work that's
| necessary to package it and upload. You just type `cargo
| publish` and you're done (after filling out metadata in
| Cargo.toml). Even if someone wouldn't upload it to crates.io
| as a Rust crate you can just add a single line to your
| Cargo.toml: package_name = { git =
| "https://github.com/user/repo", rev = "revision" }
|
| and you're done, you can use it as a dependency.
| dgfitz wrote:
| I think you moved the goalposts. I can configure a CMake
| file to pull a GitHub repo, which seems similar enough.
| Spivak wrote:
| I think the difference is that you can pip install a
| github url and it will work, it will even work if the
| upstream has done nothing to package it.
|
| I think the issue could be broadly defined as how
| difficult it is how difficult it is to take someone
| else's code and use it as part of your project. For C/C++
| the answer can be completely trivial to a massive pain in
| the ass.
| mattpallissard wrote:
| Oh I dunno. With cmake it really is pretty straight
| forward. You can pull from VCS, a tarball, even use a git
| submodule.
|
| If it's another Cmake project, that's the happy path.
| Easy peasy. If it's not you still have the ability to run
| ./configure && make or evoke whatever incantation is in
| the dependency's requirements. I'm not the hugest fan of
| cmake, but I've worked with it quite a bit and it's a
| much more pleasant story than other languages I've used a
| lot like python, JavaScript, OCaml (which I love), etc.
|
| I do find rust and go dependency management a little
| simpler due to the prescribed nature of them, but once
| you get off the happy path, the flexibility of C land is
| tough to beat. It sort of matches the language stories
| themselves; you have more control and have to do a bit
| more yourself. It's all about trade offs.
| rddbs wrote:
| How often do folks venture off the happy path with Rust
| dependencies? Personally I've never once found myself in
| that situation.
| AlotOfReading wrote:
| I've done it before to integrate rust into polyglot build
| systems. There's a surprisingly long history of build
| systems trying and failing to implement rust builds
| without the "happy path" of simply wrapping cargo. As far
| as I know no one's ever succeeded.
| vlovich123 wrote:
| The main difference being that Cargo is both for distributing
| and building locally AND it's the blessed way of building all
| Rust projects. This means that as long as you have a copy of
| the codebase, it's going to be using Cargo & you can add it
| with Cargo regardless of it being published formally to
| crates.io (the copy can even be remote since you can build
| from a git reference directly). Python packaging requires
| more work although there's typically no build step so you can
| probably just __import__ the path and move on. JS is closer
| to Rust in that package.json is the standard way to manage
| components and you can import them even if they're not
| published via the npm registry.
|
| Pretending the situation isn't very different for C++ is
| completely ignoring the standard committee's complete
| abdication of standardizing a build system (which by the way
| if they're not going to do, why are they bothering to
| standardize anything?)
| carom wrote:
| What was particularly difficult about it? Sometimes modifying
| someone else's code to build statically or on another platform
| is tricky. Linking is generally just include dir, lib path, and
| lib though.
| lairv wrote:
| The library was duckdb
| (https://duckdb.org/docs/installation/), and here are some of
| the issues I ran into:
|
| - trying to compile against the prebuilt duckdb_static.so
| file got me a ton of undefined reference error, I asked about
| this on their discord and it seems to be a knwon issue, there
| are additional dependencies that are not part of the release
| so I had to build it myself
|
| - the library uses CMake but it contains a Makefile and they
| recommend using that to build it
|
| - It seems like on windows, if you create a dynamic library
| you have to add __declspec(dllexport) before each function.
| DuckDB has a #ifdef DUCKDB_STATIC_BUILD to toggle/disable it
| which isn't documented anywhere, you have to read the code
|
| I'm sure someone will tell me that this is very standard and
| shouldn't take me 3 days to figure it out, but with basic
| knowledge of cmake and build systems that's a bit of a pain,
| and there's no other language where you have to do that
| jpc0 wrote:
| CMake, the defacto if not standard build system, when
| correctly setup, does all this for you.
|
| Your argument is along the lines of "the maintainer of X
| rust package didn't setup cargo correctly and it's
| impossible to include in my project, rust is a horrible
| language". You can absolutely make an argument that the
| lack of a standard build system is a pain point, and well
| it's C++ you get to be a special snowflake and use a
| makefile instead of CMake but then the onus is on you to
| provide correct documentation.
| lairv wrote:
| In the case of duckdb they provide proper packages for
| pip, cargo, npm, go get, and the only one that seems like
| a PITA to use is the C/C++ dependencies, even though the
| package is written is C++, so I think this tells
| something about C++ dependency management
| jpc0 wrote:
| You seem to be agreeing with me then, weird take to do it
| while sounding like you disagree...
|
| As I said, you can make the argument C++ build systems
| are no good. However the argument originally made is that
| C++ the language caused these issues when in reality the
| package maintainer hasn't put in the effort to properly
| document and fix known issues in their chosen build
| system for C++.
|
| The fact that they in fact have built out proper packages
| for pip, cargo, npm and go tells me they have the
| necessary expertise on the team and made an active choice
| to not do the same for C++. Create an issue with the
| maintainer.
| jodrellblank wrote:
| The argument originally made was " _You can read front-
| to-cover books about every details of C++ semantics and
| it 'll still be a PITA to work on real world projects_"
|
| Which is not disagreeing with you just because you are
| explaining/disputing the reason it was a PITA.
| jpc0 wrote:
| Seeing as it's Christmas Eve and I has nothing better to
| do...
|
| Duckdb own documentation says the C++ API is internal and
| you should use the C API[1]
|
| The makefile also has a 'bundle-library' option which
| seems to be exactly what you were looking for, it
| generates a statically linked library which is what the
| Golang package is using, probably others too but that's
| the one I checked first.
|
| This is purely a documentation problem, the build system
| does what is needed it seems. Create an issue, or better
| yet, add the necessary documentation...
|
| 1. https://duckdb.org/docs/api/cpp
| lairv wrote:
| I used the C api but I did miss the 'bundle-library'
| option, will look into that
| jpc0 wrote:
| I definitely don't blame you for missing it.
|
| I found it by looking at the go package because they
| claimed they are statically linking there.
| oconnor663 wrote:
| > the maintainer of X rust package didn't setup cargo
| correctly and it's impossible to include in my project
|
| That basically never happens, which is the point.
| tdullien wrote:
| I have seen way more projects with very broken CMake
| integration than rust packages with broken cargo setup.
|
| CMake _is_ a pain.
| lr1970 wrote:
| > trying to compile against the prebuilt duckdb_static.so
|
| Typically you statically link against _.a object
| library._.so are shared objects intended for dynamical
| linking only. Does duckdb provide something like duckdb.a ?
| anonnon wrote:
| I had a similar reaction returning to C++ a few years ago, and
| getting exposed to stuff like lambdas, smart pointers, and
| template metaprogramming painpoints being fixed. One especially
| nice thing about C++ is GCC, which lets you use relatively recent
| features even on obscure HW/OS architectures that other, trendier
| languages ignore. For example, you can use modern C++ features,
| at least upto C++17, on OpenBSD.
| jimberlage wrote:
| Every article like this I scan to see if the author had previous
| C++ experience. And every article, they do.
|
| I will be very impressed and curious if I find a glowing article
| about C++ from someone who didn't grow up knowing it as a
| smaller, simpler language.
|
| The C++ community needs enthusiastic converts who didn't do it
| back in the 2000s if it's going to stay relevant.
| unclad5968 wrote:
| I learned c++ after c++20 and after several attempts to enjoy
| rust, c#, go, and C, I always come back to c++ as the most
| enjoyable language to develop.
| jimberlage wrote:
| Nice! If you blog at all your perspective would be super
| interesting to hear.
| NooneAtAll3 wrote:
| I'm gonna be weird and not engage in language war (I love c++)
|
| but, dear author:
|
| > +95% of the compiler errors
|
| this. this is unforgivable
|
| +X means "additional X". As in "I have Y and I add +X to it".
| When you are invited to an event, your invite states you can take
| your +1 with you (one more person that will come within the same
| invitation)
|
| if you want to say "more than", you use X+ !! as in "95%+".
| Because you have some X amount, and you add some more to get
| X+...
|
| get it together. you're awesome
| anentropic wrote:
| > I remember insane discussions with people who thought adding
| two numbers with a template was "faster" than adding two numbers
| directly, even though the assembly language output was exactly
| the same.
|
| I know almost nothing about C++ and have never programmed in
| it... but I thought that the point of that kind of 'template
| metaprogramming' was that the code got executed at compile time
| instead of runtime?
|
| i.e. instead of generating identical assembly output the goal
| would have been to output a constant value
| ch33zer wrote:
| As per usual with c++ it depends. In some situations things are
| guaranteed to be compile time evaluated. E.g. even in early
| templates this would need to work:
|
| Func<1+2>();
|
| Something like this there's no guarantees around:
|
| template <A, B> int Func() { return A + B; }
|
| For almost all compilers it should constant fold this into a
| constant but in theory it could end up with an add instruction.
| Basically we can't second guess the author here because it
| depends on the specifics.
| andrewflnr wrote:
| > I firmly believe that for creativity to blossom you need to be
| able to get your idea out without fear of criticism and shame.
|
| This section is, it seems to me, the linchpin of the "fun"
| argument. But you've been able to do that with all the other
| languages too, all this time. The much-loathed and feared Rust
| Evangelism Strikeforce doesn't actually come to your house and
| make you use a bunch of generic-heavy code from crates.io. The
| React people can't stop you from using vanilla Js. The worst they
| can really do is send you mean tweets, but Shaw thinks this is a
| lethal threat to his creativity, enough to switch language
| ecosystems over. For an article written in a superficially
| rebellious, lone-wolf tone, that's kinda sad.
| mcdeltat wrote:
| This article seems kinda confused. It makes a lot of points, but
| I'm struggling to extract why that means C++ is more/less fun.
|
| The simultaneous description of modern C++ as "extremely high
| quality" and yet pervasive legacy bs, horrible tooling, etc is
| confusing. They say unique_ptr is great yet they "really hate
| RAII". Many of the discussed topics are largely irrelevant or
| incorrect. Metaprogramming used to be everywhere but now isn't
| (what?? Take a look at concepts)? C++ has the best graphics
| libraries (surely not true)? Installing Python is harder than
| C++? These seems like odd obsessions of the author, with little
| relation to the argument.
|
| I think the author just finds C++ fun for some complex
| combination of personal factors, which is fine. Perhaps partly
| due to a "hacker" type personality. Some of the most fun I've had
| with programming has been C++, due to its performance and
| technicality. At the same time, C++ is in practice crap for
| "real" software development where your own short-term enjoyment
| is not paramount (for a billion reasons we all know). C++ is a
| deeply conflicted language, scarred by decades of legacy and
| politics. Ignoring the reality of C++ is the biggest mistake of
| those who discuss it. My attitude towards C++ these days is of
| tiredness. I don't want to jump through the hoops C++ has thrown
| at me for the past many years. We don't need to beat an already
| long dead horse. It's ok to let C++ be what it is.
| mst wrote:
| > I think the author just finds C++ fun for some complex
| combination of personal factors, which is fine. Perhaps partly
| due to a "hacker" type personality.
|
| I think that sums up the point of the article just fine.
|
| To me at least, it's not so much that it's confused as that
| it's him being excited about having fun and doing his best to
| share his joy. Which means that, sure, it's not a proper essay
| at all, it's not really trying to convince you to agree so much
| as saying "if you find this relatable without me trying to
| actively convince you, maybe you'd find it fun too."
|
| I think given you've been mugged by reality in commercial work
| to the point of tiredness, your not finding it to make sense at
| all is completely understandable, though.
|
| I'm currently having a blast writing javascript of all things,
| and I imagine if I wrote up a similar blog post explaining why
| it'd come across just as badly to somebody burned out on the
| last decade of commercial javascript too.
|
| But I'm glad he's having fun, and I'm glad he decided to share
| the joy.
| PittleyDunkin wrote:
| I am a bona fide C++ hater, but that's just because I resent
| working on it for professional code that needs to work reliably
| with coworkers I don't entirely trust. For personal projects it's
| one of the most satisfying coding contexts I've ever worked and
| it is indeed a blast to have such fine-grained control over
| execution.
|
| I abandoned the language about a decade ago and I don't see
| myself looking back. My projects these days need long-term
| reliability more than anything and rust + cd/ci hits a sweet
| spot. That said, I do miss the thrill of designing and executing
| a program that runs in a certain way exactly as I intended and
| knowing that it was my expertise and insight that allowed this
| execution. Would I want to work with someone that was driven by
| that? Hell no! But it is personally a joy I won't forget.
|
| Other inexcusable pain points: the build systems and package
| management is an absolute nightmare; the pre-processor feels like
| a sadistic joke; the syntax is horrible; there's so much cruft in
| the runtime you need years of experience to not machine-gun your
| foot off by using the most obvious tool at your disposal. But in
| a sense this just increases the joy of shipping a working
| executable with all your cleverness and blood and tears wrapped
| with a bow.
| nnadams wrote:
| Kudos for one of the most relatable descriptions of C++ I've
| read.
|
| I did a couple years writing C/C++ professionally, and I hope
| to not go back to that. Too many hours debugging other people's
| code, suffering vague integration issues, and just trying to
| get the build system spaghetti to run.
| mempko wrote:
| Work should be fun too, not just personal projects. I've
| noticed that over the last 10 years, the tech world has seemed
| to lose this idea. I blame this on the large tech companies who
| seem to take the best people and put them in an adult prison.
| Granted a prison with good food and soft chairs.
|
| Even startups seem to be less fun. It seems the VC world
| foments a narrow window of thought with a lot of copy cat
| startups doing the same thing. Fads, lots of fads.
|
| I use C++ for every new project because I know if I need to
| build something myself, I can do it. Using frameworks all the
| time sucks because frameworks never work the way you want.
| Especially if it deals with the core of the project.
|
| If you can build it yourself, then do it, otherwise use a
| framework. And if you can build it yourself, C++ is a great
| tool because it can do everything and doesn't get in your way
| in all the important ways. Meaning, I can express my mental
| model directly in C++, where a language like Rust might
| complain I'm doing an unsafe thing. Sometimes I think in
| pointers damned and pointers are a great thing!
|
| Lets bring fun back! Not just in our personal lives, but work
| too!
| Animats wrote:
| The fundamental problem with C++ is that it has hiding
| ("abstraction") without safety. That's rare.
|
| - C -- No hiding, no safety
|
| - Python, Javascript, LISP, other interpreted languages -- hiding
| with safety
|
| - Pascal, Ada, Modula, Rust -- hiding with safety
|
| - C++ -- hiding without safety.
|
| C++ is, decades late, trying to get to hiding with safety. But
| there's too much legacy.
| gpderetta wrote:
| Well C has functions. Isn't that the original hiding
| abstraction?
| pornel wrote:
| It is an abstraction, but the safety requirements are neither
| enforced nor abstracted away.
|
| C's type system can't communicate how long pointers are valid
| for, when and where memory gets freed, when the data may be
| uninitialized, what are the thread-safety requirements, etc.
| The programmer needs to know these things, and manually
| ensure the correct usage.
| everyone wrote:
| C++ is great, but I hate .h files.. I'm kind of shocked that some
| tool to automate writing .h files isnt the the standard.
| moth-fuzz wrote:
| I'm of two minds when I see comments complaining about header
| files. Practically speaking, I think "have the preprocessor copy
| & paste source files together" is a bit of a hackjob, but,
| _conceptually_ speaking, having your interface and implementation
| separate is ultimately a good thing.
|
| The problem of course lies not with header files, but C++ the
| language, as all public fields and private fields must be
| specified in the class declaration so that the compiler knows the
| memory layout. It's kind of useless in that sense. You can move
| private methods out to a separate source file, but, you don't
| gain much in doing so, at least in terms of strict encapsulation.
| And of course, if you use templates at all, you can no longer
| even do that. Which is its own can of worms.
|
| Unfortunately, none of these problems are problems that modules
| solve. Implementations very much disagree on interfaces vs
| implementations, precompiled vs simply included, etc etc. In my
| own usage of modules I've just found it to be header files with
| different syntax. Any API implemented via modules is still very
| leaky - it's hard to just import a module and know what's truly
| fair for application usage or not. You still ultimately have to
| rely on documentation for usage details.
|
| At the end of the day I don't really care how the implementation
| puts together a particular feature, I care about how it affects
| the semantics and usability of the language. And modules do not
| really differ in proper usage from headers, even though the whole
| backend had to be changed, the frontend ends up being the same.
| So it's net nothing.
|
| All said and done, when it comes to defining library APIs, I
| prefer C. No public/private, you just have some data laid out a
| particular way, and some functions to operate on it. The header
| file is essentially just a symbol table for the binary code - and
| said code can be a .c file or a .o file or even a .a or .lib or
| .dll or whatever - C doesn't care. Raw functionality, raw
| usability. No hoops.
| holografix wrote:
| Tl;dr programming as a hobby building what and how I want is much
| more fun than doing it for money and being told what to do.
| globalnode wrote:
| I have the luxury of only writing software for myself, which is
| almost always Python, but after reading this ill go back and have
| another look at C++. Did one big project in C++ after uni but
| then never touched it again.
| 8n4vidtmkvmk wrote:
| It takes some getting used to. I wrote it for about 10 years
| then didn't touch it for 10 years and now I write it full time
| again. Took a few months to get up speed again and stop
| shooting myself in the foot.
| akoboldfrying wrote:
| >I really hate RAII.
|
| I'm baffled by this. Deterministic destruction (necessary and
| basically sufficient for RAII) was one of the best design
| decisions in C++, I think. RAII means you _can 't_ forget to
| clean up a resource. You don't have to type anything for it to
| get cleaned up at the right time, it just happens. It's basically
| what GC promised developers, except for all resource types, not
| just memory. Your code gets shorter _and_ more correct.
|
| I'm extremely curious to hear how this could ever be bad.
| AnimalMuppet wrote:
| RAII isn't just about the destructor, though. It's about
| writing the _constructor_ in such a way that you can always
| safely destroy the object. If you don 't write the constructor
| right, RAII might become something you really hate, because it
| could blow up on you any time the destructor fires.
| AHTERIX5000 wrote:
| "I really hate RAII" but smart pointers are great?
| g42gregory wrote:
| For me, it's basically C++ for low-level, Python for high-level,
| Java for insanely large corporate codebases, JavaScript (oh
| boy...) for the Web. Tons of better languages are out there, but
| they lack the same level of support, tooling and libraries'
| availability.
| EVa5I7bHFq9mnYK wrote:
| There were 91 occurrences of the word "rust" in 264 comments so
| far.
| sseagull wrote:
| Only 7 instances of "footgun" (or a variation) though. HN is
| slacking - must be the holidays
| teleforce wrote:
| > Well, actually the Rust weirdos will bother you but they're
| usually too busy making the borrow checker happy to actually get
| anything done so you can ignore them.
|
| Ouch...
| medo-bear wrote:
| I plead the 10th
|
| https://en.m.wikipedia.org/wiki/Greenspun%27s_tenth_rule
| doug_durham wrote:
| The metaprogramming metapocolypse resonated with me. In the late
| 1990's the entire software world got "pattern disease". Yikes. We
| are still paying the price.
| thdhhghgbhy wrote:
| >shame grifters
|
| Love this. This is an old post though right, still talking about
| C+11?
| anothername12 wrote:
| I think I will take another look. I recently helped my grandson
| with his university C++ assignment. It was a lot better than I
| remember C++ in the 90s.
|
| Fun wise though, I get the most fun with dynamic languages that
| are highly interactive like Forth, Common Lisp and Smalltalk. I
| don't have to drop out of the zone to kick the compiler all the
| time.
| jebarker wrote:
| > I recently helped my grandson with his university C++
| assignment.
|
| That is awesome. I hope if my kids have kids i'll be of some
| technical use to them too!
___________________________________________________________________
(page generated 2024-12-24 23:02 UTC)