fouronnes3 26 minutes ago

This is a good article but it only scratches the surface, as is always the case when it comes to C++.

When I made a meme about C++ [1] I was purposeful in choosing the iceberg format. To me it's not quite satisfying to say that C++ is merely complex or vast. A more fitting word would be "arcane", "monumental" or "titanic" (get it?). There's a specific feeling you get when you're trying to understand what the hell is an xvalue, why std::move doesn't move or why std::remove doesn't remove.

The Forest Gump C++ is another meme that captures this feeling very well (not by me) [2].

What it comes down to is developer experience (DX), and C++ has a terrible one. Down to syntax and all the way up to package management a C++ developper feels stuck to a time before they were born. At least we have a lot of time to think about all that while our code compiles. But that might just be the price for all the power it gives you.

[1] https://victorpoughon.github.io/cppiceberg/

[2] https://mikelui.io/img/c++_init_forest.gif

  • jandrese 17 minutes ago

    In Linuxland you at least have pkg-config to help with package management. It's not perfect but neither is any other package management solution.

    If I'm writing a small utility or something the Makefile typically looks something like this:

        CC=clang
        PACKAGES=libcurl libturbojpeg
        CFLAGS=-Wall -pedantic --std=gnu17 -g $(shell pkg-config --cflags $(PACKAGES))
        LDLIBS=$(shell pkg-config --libs $(PACKAGES))
    
        ALL: imagerunner
    
        imagerunner: imagerunner.o image_decoder.o downloader.o
scj 17 minutes ago

"you can write perfectly fine code without ever needing to worry about the more complex features of the language. You can write simple, readable, and maintainable code in C++ without ever needing to use templates, operator overloading, or any of the other more advanced features of the language."

You could also inherit a massive codebase old enough to need a prostate exam that was written by many people who wanted to prove just how much of the language spec they could use.

If selecting a job mostly under the Veil of Ignorance, I'll take a large legacy C project over C++ any day.

gmueckl 10 minutes ago

C++ will always stay relevant. Software has eaten the world. That transition is almost complete now. The languages that were around when it happened will stay deeply embedded in our fundamental tech stacks for another couple decades at least, if not centuries. And C and C++ are the lion's share of that.

COBOL sticks around 66 years after its first release. Fortran is 68 years old and is still enormously relevant. Much, much more software was written in newer languages and has become so complex that replacements have become practically impossible (Fuchsia hasn't replaces Linux in Google products, wayland isn't ready to replace X11 etc)

Night_Thastus 11 minutes ago

When it comes to programming, I generally decide my thoughts based on pain-in-my-ass levels. If I constantly have to fiddle with something to get it working, if it's fragile, if it frequently becomes a pain point - then it's not great.

And out of all the tools and architecture I work with, C++ has been some of the least problematic. The STL is well-formed and easy to work with, creating user-defined types is easy, it's fast, and generally it has few issues when deploying. If there's something I need, there's a very high chance a C or C++ library exists to do what I need. Even crossing multiple major compiler versions doesn't seem to break anything, with rare exceptions.

The biggest problem I have with C++ is how easy it is to get very long compile times, and how hard it feels like it is to analyze and fix that on a 'macro' (whole project) level. I waste ungodly amounts of time compiling. I swear I'm going to be on deaths door and see GCC running as my life flashes by.

Some others that have been not-so-nice:

* Python - Slow enough to be a bottleneck semi-frequently, hard to debug especially in a cross-language environment, frequently has library/deployment/initialization problems, and I find it generally hard to read because of the lack of types, significant whitespace, and that I can't easily jump with an IDE to see who owns what data. Also pip is demon spawn. I never want to see another Wheel error until the day I die.

* VSC's IntelliSense - My god IntelliSense is picky. Having to manually specify every goddamn macro, one at a time in two different locations just to get it to stop breaking down is a nightmare. I wish it were more tolerant of having incomplete information, instead of just shutting down completely.

* Fortran - It could just be me, but IDEs struggle with it. If you have any global data it may as well not exist as far as the IDE is concerned, which makes dealing with such projects very hard.

* CMake - I'm amazed it works at all. It looks great for simple toy projects and has the power to handle larger projects, but it seems to quickly become an ungodly mess of strange comments and rules that aren't spelled out - and you have no way of stepping into it and seeing what it's doing. I try to touch it as infrequently as possible. It feels like C macros, in a bad way.

lordleft 44 minutes ago

Great article. Modern C++ has come a really long way. I think lots of people have no idea about the newer features of the standard library and how much they minimize footguns.

  • sunshowers 28 minutes ago

    Lambdas, a modern C++ feature, can borrow from the stack and escape the stack. (This led to one of the more memorable bugs I've been part of debugging.) It's hard to take any claims about modern C++ seriously when the WG thought this was an acceptable feature to ship.

    Of course, the article doesn't mention lambdas.

    • im3w1l 16 minutes ago

      Why wouldn't it be acceptable to ship? This is how everything works in C++. You always have to mind your references.

      • sunshowers 12 minutes ago

        Exactly! This is my problem with the C++ community's culture. At no point is safety put first.

nzeid 19 minutes ago

> Just using Rust will not magically make your application safe; it will just make it a lot harder to have memory leaks or safety issues.

You know, not sure I even agree with the memory leaks part. If you define a memory leak very narrowly as forgetting to free a pointer, this is correct. But in my experience working with many languages including C/C++, forgotten pointers are almost never the problem. You're gonna be dealing with issues involving "peaky" memory usage e.g. erroneously persistent references to objects or bursty memory allocation patterns. And these occur in all languages.

whobre 16 minutes ago

> C++ is very old, in fact, it came out in 1985, to put it into perspective, that’s 4 years before the first version of Windows was released

Nitpick, I guess, but Windows 1.0 was released in November 1985:

https://en.m.wikipedia.org/wiki/Windows_1.0

jasperry 22 minutes ago

The author argues that if rewriting a C++ codebase in Rust makes it more memory-safe, that's not because Rust is memory-safe. What?

justicehunter 15 minutes ago

I'm not sure what I feel about the article's point on boost. It does contribute a lot to the standard library and does provide some excellent libraries, like boost.Unordered

AHTERIX5000 27 minutes ago

I write C++ daily and I really can't take seriously arguments how C++ is safe if you know what you're doing like come on. Any sufficiently large and complex codebases tend to have bugs and footguns and using tools like memory safe languages limit blast radius considerably.

Smart pointers are neat but they are not a solution for memory safety. Just using standard containers and iterators can lead to lots of footguns, or utils like string_view.

franky47 28 minutes ago

What’s a good (ie: opinionated) code formatter and unit test framework for C++ these days?

I just had a PR on an old C++ project, and spending 8 years in the web ecosystem have raised the bar around tooling expectations.

Rust is particularly sweet to work with in that regard.

  • lang4d 15 minutes ago

    My go to for formatting would be clang-format, and for testing gtest. For more extensive formatting (that involves the compiler) clang-tidy goes a long way

  • IshKebab 14 minutes ago

    The only formatter is clang-format, and it isn't very good. Better than nothing though.

  • jonstewart 16 minutes ago

    Catch2 is great as a unit test framework.

    Running unit tests with the address sanitizer and UB sanitizer enabled go a long way towards addressing most memory safety bugs. The kind of C++ you write then is a far cry from what the haters complain about with bad old VC6 era C++.

g42gregory 15 minutes ago

I am not sure C++ needs a defense. Especially after C++ 11 cleanup.

IshKebab 15 minutes ago

Terrible article.

> you can write perfectly fine code without ever needing to worry about the more complex features of the language

Not really because of undefined behaviour. You must be aware of and vigilant about the complexities of C++ because the compiler will not tell you when you get it wrong.

I would argue that Rust is at least in the same complexity league as C++. But it doesn't matter because you don't need to remember that complexity to write code that works properly (almost all of the time anyway, there are some footguns in async Rust but it's nothing on C++).

> Now is [improved safety in Rust rewrites] because of Rust? I’d argue in some small part, yes. However, I think the biggest factor is that any rewrite of an existing codebase is going to yield better results than the original codebase.

A factor, sure. The biggest? Doubtful. It isn't only Rust's safety that helps here, it's its excellent type system.

> But here’s the thing: all programming languages are unsafe if you don’t know what you’re doing.

Somehow managed to fit two fallacies in one sentence!

1. The fallacy of the grey - no language is perfect therefore they are all the same.

2. "I don't make mistakes."

> Just using Rust will not magically make your application safe; it will just make it a lot harder to have memory leaks or safety issues.

Not true. As I said already Rust's very strong type system helps to make applications less buggy even ignoring memory safety bugs.

> Yes, C++ can be made safer; in fact, it can even be made memory safe. There are a number of libraries and tools available that can help make C++ code safer, such as smart pointers, static analysis tools, and memory sanitizers

lol

> Avoid boost like the plague.

Cool, so the ecosystem isn't confusing but you have to avoid one of the most popular libraries. And Boost is fine anyway. It has lots of quite high quality libraries, even if they do love templates too much.

> Unless you are writing a large and complex application that requires the specific features provided by Boost, you are better off using other libraries that are more modern and easier to use.

Uhuh what would you recommend instead of Boost ICL?

I guess it's a valiant attempt but this is basically "in defense of penny farthings" when the safety bicycle was invented.

EGreg 22 minutes ago

Python’s “there should be one obvious way to do it” slogan often collides with reality these days too, since the language sprawled into multiple idioms just like C++: for printing you can use print("hi"), f-strings like f"hi {x}", .format(), % formatting, or concatenation with +; for loops you can iterate with for i in range(n), list comprehensions [f(i) for i in seq], generator expressions (f(i) for i in seq), or map/filter/lambda; unpacking can be done with a,b=pair, tuple() casting, slicing, *args capture, or dictionary unpacking with *; conditionals can be written with if/else blocks, one-line ternary x if cond else y, and/or short-circuit hacks, or pattern matching match/case; default values can come from dict.get(k,default), x or default, try/except, or setdefault; swapping variables can be done with a,b=b,a, with a temp var, with tuple packing/unpacking, or with simultaneous assignment; joining strings can be done with "".join(list), concatenation in a loop, reduce(operator.add, seq), or f-strings; reading files can be open().read(), iterating line by line with for line in f, using pathlib.Path.read_text(), or with open(...) as f; building lists can be done with append in a loop, comprehensions, list(map(...)), or unpacking with [*a,*b]; dictionaries can be merged with {*a,*b}, a|b (Python 3.9+), dict(a,*b), update(), or comprehensions; equality and membership checks can be ==, is, in, any(...), all(...), or chained comparisons; function arguments can be passed positionally, by name, unpacked with * and \*, or using functools.partial; iteration with indexes can be for i in range(len(seq)), for i,x in enumerate(seq), zip(range(n),seq), or itertools; multiple return values can be tuples, lists, dicts, namedtuples, dataclasses, or objects; even truthiness tests can be if x:, if bool(x):, if len(x):, or if x != []:. Whew!

  • lyu07282 10 minutes ago

    But hey at least python forces you to use whitespace properly hinthinthint

fithisux 27 minutes ago

"Rust shines in new projects where safety is the priority, while C++ continues to dominate legacy systems and performance-critical domains."

the truth