Remix.run Logo
s20n 5 days ago

I believe most C++ gripes are a classic case of PEBKAC.

One of the most common complaints is the lack of a package manager. I think this stems from a fundamental misunderstanding of how the ecosystem works. Developers accustomed to language-specific dependency managers like npm or pip find it hard to grasp that for C++, the system's package manager (apt, dnf, brew) is the idiomatic way to handle dependencies.

Another perpetual gripe is that C++ is bad because it is overly complex and baroque, usually from C folks like Linus Torvalds[1]. It's pretty ironic, considering the very compiler they use for C (GCC), is written in C++ and not in C.

[1]: Torvalds' comment on C++ <https://harmful.cat-v.org/software/c++/linus>

ameliaquining 5 days ago | parent | next [-]

> Developers accustomed to language-specific dependency managers like npm or pip find it hard to grasp that for C++, the system's package manager (apt, dnf, brew) is the idiomatic way to handle dependencies.

Okay, but is that actually a good idea? Merely saying that something is idiomatic isn't a counterargument to an allegation that the ecosystem has converged on a bad idiom.

For software that's going to be distributed through that same package manager, yes, sure, that's the right way to handle dependencies. But if you're distributing your app in a format that makes the dependencies self-contained, or not distributing it at all (just running it on your own machines), then I don't see what you gain from letting your operating system decide which versions of your dependencies to use. Also this doesn't work if your distro doesn't happen to package the dependency you need. Seems better to minimize version skew and other problems by having the files that govern what versions of dependencies to use (the manifest and lockfile) checked into source control and versioned in lockstep with the application code.

Also, the GCC codebase didn't start incorporating C++ as an implementation language until eight years after Linus wrote that message.

ryao 5 days ago | parent | prev | next [-]

GCC was originally written in GNU C. Around GCC 4.9, its developers decided to switch to a subset of C++ to use certain features, but if you look at the codebase, you will see that much of it is still GNU C, compiled as GNU C++.

There is nothing you can do in C++ that you cannot do in C due to Turing Completeness. Many common things have ways of being done in C that work equally well or even better. For example, you can use balanced binary search trees in C without type errors creating enormous error messages from types that are sentences if not paragraphs long. Just grab BSD’s sys/tree.h, illumnos’ libuutil or glib for some easy to use balanced binary search trees in C.

AdieuToLogic 5 days ago | parent | next [-]

> There is nothing you can do in C++ that you cannot do in C due to Turing Completeness.

While this is technically true, a more satisfying rationale is provided by Stroustrup here[0].

> Many common things have ways of being done in C that work equally well or even better. For example, you can use balanced binary search trees in C without type errors creating enormous error messages from types that are sentences if not paragraphs long. Just grab BSD’s sys/tree.h, illumnos’ libuutil or glib for some easy to use balanced binary search trees in C.

Constructs such as sys/tree.h[1] replicate the functionality of C++ classes and templates via the C macro processor. While they are quite useful, asserting that macro-based definitions provide the same type safety as C++ types is simply not true.

As to the whether macro use results in "creating enormous error messages" or not, that depends on the result of the textual substitution. I can assure you that I have seen reams of C compilation error messages due to invalid macro definitions and/or usage.

0 - https://www.stroustrup.com/compat_short.pdf

1 - https://cgit.freebsd.org/src/tree/sys/sys/tree.h

AdieuToLogic 5 days ago | parent | prev [-]

Where C macros provide functionality C++ classes and/or templates cannot is stringification of their argument(s).

For example:

  #include <iostream>

  #define SQL(statement) #statement

  int main (int ac, const char *av[])
  {
   const char *select = SQL(select * from some_table);

   std::cout << select << std::endl;

   return 0;
  }
viraptor 5 days ago | parent | prev | next [-]

> find it hard to grasp that for C++, the system's package manager (apt, dnf, brew) is the idiomatic way to handle dependencies.

It's really not about being hard to grasp. Once you need a different dependency version than the system provides, you can't easily do it. (Apart from manual copies) Even if the library has the right soname version preventing conflicts (which you can do in C, but not really C++ interfaces), you still have multiple versions of headers to deal with. You're losing features by not having a real package manager.

DarkNova6 3 days ago | parent | prev [-]

> Developers accustomed to language-specific dependency managers like npm or pip find it hard to grasp that for C++, the system's package manager (apt, dnf, brew) is the idiomatic way to handle dependencies.

This is a strawman argument. Just because pip and npm are a mess and security liabilities does not make the c++ situation less bad. A fair comparison would be for languages that got their act together and use cargo, maven or nuget.

Linus is also not alone with his opinion in favouring Rust over C++. I would be hard pressed to use his persona in a negative case.