←back to thread

In Defense of C++

(dayvster.com)
185 points todsacerdoti | 1 comments | | HN request time: 0s | source
Show context
fouronnes3 ◴[] No.45268145[source]
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

replies(4): >>45268251 #>>45271645 #>>45273605 #>>45277835 #
jandrese ◴[] No.45268251[source]
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
replies(1): >>45268768 #
duped ◴[] No.45268768[source]
Consider that to do this you must:

- Use a build system like make, you can't just `c++ build`

- Understand that C++ compilers by default have no idea where most things are, you have to tell them exactly where to search

- Use an external tool that's not your build system or compiler to actually inform the compiler what those search paths are

- Oh also understand the compiler doesn't actually output what you want, you also need a linker

- That linker also doesn't know where to find things, so you need the external tool to use it

- Oh and you still have to use a package manager to install those dependencies to work with pkg-config, and it will install them globally. If you want to use it in different projects you better hope you're ok with them all sharing the same version.

Now you can see why things like IDEs became default tools for teaching students how to write C and C++, because there's no "open a text editor and then `c++ build file.cpp` to get output" for anything except hello world examples.

replies(7): >>45269381 #>>45270904 #>>45270987 #>>45271280 #>>45273544 #>>45277859 #>>45343902 #
jlarocco ◴[] No.45271280[source]
It's really not that big of a deal once you know how it works, and there are tools like CMake and IDEs that will take care of it.

On Windows and OSX it's even easier - if you're okay writing only for those platforms.

It's more difficult to learn, and it seems convoluted for people coming from Python and Javascript, but there are a lot of advantages to not having package management and build tooling tightly integrated with the language or compiler, too.

replies(6): >>45273345 #>>45273469 #>>45273881 #>>45275446 #>>45275472 #>>45277989 #
Defletter ◴[] No.45273469[source]
This is pure Stockholm syndrome. If I were forced to choose between creating a cross-platform C++ project from scratch or taking an honest to god arrow to the knee, the arrow would be less painful.
replies(3): >>45273611 #>>45274871 #>>45278065 #
AlienRobot ◴[] No.45274871[source]
I don't want any arrows in my knees but I agree.

The main reason I don't want to use C/C++ are the header files. You have to write everything in a header file and then in an implementation file. Every time you want to change a function you need to do this at least twice. And you don't even get fast compilation speed compared to some languages because your headers will #include some library that is immense and then every header that includes that header will have transitive header dependencies, and to solve this you use precompiled headers which you might have to set up manually dependending on what IDE you are using.

It's all too painful.

replies(2): >>45278311 #>>45343882 #
1. jstimpfle ◴[] No.45278311[source]
It gets better with experience. You can have a minimal base layer of common but rarely changing functionality. You can reduce static inline functions in headers. You reduce data structure definitions, but put only forward declarations in header files. (Don't use C++ methods, at least don't put them in an API, because they force you to expose your implementation details needlessly). You can separate data structures from functions in different header files. Grouping functions together with types is often a bad idea since most useful functionality combines data from two or more "unrelated" types -- so you'd rather make function headers "by topic" than putting them alongside types.

I just created a subsystem for a performance intensive application -- a caching layer for millions or even billions of objects. The implementation encompasses over a 1000 LOC, but the header only includes <stdint.h>. There are about 5 forward struct declarations and maybe a dozen function calls in that API.

To a degree it might be stockholm syndrome, but I feel like having had to work around a lot of C's shortcomings I actually learned quite a lot that helps me in architecting bigger systems now. Turns out a lot of the flexibility and ease that you get from more modern languages mostly allows you to code more sloppily, but being sloppy only works for smaller systems.