Remix.run Logo
▲ Joker_vD 5 hours ago

For one reason, it is because C++ runtime (and its standard library) is a whole own can of worms which most people would rather not touch if they can afford to. Which they mostly can.

> Sure, C++ has its own downsides

"Sure, getting your eyes gouged out has its downsides, but is it better to read that awful mess of macros in C instead?" The answer most people would give to this question may surprise you.

▲kccqzy 5 hours ago | parent [-]

Here we go again. Yes there are bad parts in the C++ standard library and there are good parts. But if you are just trying to do type safe generic data structures you are unlikely to touch the bad parts. Many codebases forbids parts of the standard library, e.g. LLVM forbids including <iostream>. You can forbid using parts of the standard library too.

▲Joker_vD 5 hours ago | parent | next [-]

> Yes there are bad parts in the C++ standard library and there are good parts.

Okay, other than <vector>, what are the good parts? Because as the sibling comments rightfully point out, migrating your codebase from C to C++ just to be able to use <vector> is not worth it.

The <map> is a sad joke played upon the C++ programmers by the standard committee.

▲pjmlp 5 hours ago | parent | next [-]

Strings, something that C still doesn't do properly, not even having something like SDS into the standard library.

<map> does the work just fine, not everyone has winning microbenchmarks as part of their daily work.

▲accelbred 4 hours ago | parent | next [-]

Many of the big C++ projects I've worked with have custom string types since the standard one was defficient for some reason or another.

▲jstimpfle 4 hours ago | parent [-]

Exactly, and a simple usable string type is just a struct MyString { char *buf; size_t len; }; away. Actual magic is in how you use it, where you allocate it, how you integrate allocation and formatting and logging and I/O... i.e. all the things that aren't solved by crufty complex std::string either.

▲Joker_vD 4 hours ago | parent | prev [-]

> <map> does the work just fine

It has a rather weird interface, at least until C++ 17 when some of the deficiencies were patched somewhat.

▲jstimpfle 4 hours ago | parent [-]

It's a slow generic data structure with an unintuitive API. You can use it for leetcode or for CRUD. For anything more demanding it's horrifically bloated and bad. std::string too. Whenever you see STL datatypes like even string and map, you have to deal with RAII, implicit allocations, weird operator syntax, unexpected mutation (invalidation) and so on.

(Spporting or even encouraging destructive mutation, and by this I mean not incrementing counters or anything harmless but allowing iterator invalidations and crashes, are also why std::vector is bad in my opinion, these are idiomatic APIs for 90s and 2000s programming, which we should know better to avoid in 2026).

▲Panzerschrek 3 hours ago | parent | next [-]

> For anything more demanding it's horrifically bloated and bad

C++ containers are designed for average demands. If you need something more specific, you can always use an alternative implementation. And it's better than messing with macros in pure C.

> you have to deal with RAII

What's problematic with it?

> implicit allocations

Allocations aren't implicit. It's usually clear from the documentation where allocation takes place (like in concatenating strings or copying strings).

> unexpected mutation (invalidation)

It's not the case with standard library containers. Mutating methods aren't const-qualified, so that it's clear where mutation can take place. And in C++ it's strictly recommended to mark as const everything in regular user code which shouldn't be mutated.

▲jstimpfle 3 hours ago | parent [-]

> C++ containers are designed for average demands. If you need something more specific, you can always use an alternative implementation.

As someone who has been programming exclusively in C/C++ for a long time -- the biggest selling point for these languages in 2026 is exactly being suited to doing something specific, not generic.

> Allocations aren't implicit

    std::map<int,int> m;
    m[1] = 42; // implicit alloc
    auto m2 = m; // implicit too

> in C++ it's strictly recommended to mark as const everything in regular user code which shouldn't be mutated.

Theory and practice. Making everything const correct is too painful in practice, often impossible. It's a trap for bean counters that can't focus on getting some actual useful work done. I'm being harsh to my own past self here. Counter question: why include allocation mechanics with some existing data that never gets changed? Why should we have to add much more boilerplate to get the simpler thing?

▲Panzerschrek 2 hours ago | parent [-]

> m[1] = 42; // implicit alloc

operator[] of associative containers is mutating and may allocate. It's mentioned in the documentation. And there is no operator[] overloading for const instances, so that you can't trigger an allocation by just reading elements from it.

> auto m2 = m; // implicit too

Taking a copy requires making an allocation. Do you expect some other behavior in such case?

> Making everything const correct is too painful in practice, often impossible

Maybe you are dealing with some legacy codebase (from 90s)? I have worked with multiple codebases in past 10 years or so and keeping things which shouldn't be mutated const wasn't a problem at all. All the code was written using such approach.

> why include allocation mechanics with some existing data that never gets changed

I don't think I fully understand this question. What never gets changed? In your example you are mutating a container and taking a copy of it (which can be changed later).

▲jstimpfle 2 hours ago | parent [-]

> Do you expect some other behavior in such case?

No, just saying this stuff is implicit and thus hard to read. More so the allocation on indexing assignment. and keeping things which shouldn't be mutated const wasn't a problem at all.

> and keeping things which shouldn't be mutated const wasn't a problem at all.

As soon as datastructures become more complicated and more interconnected, it's not clear anymore what const should even mean (issues are similar as with deep vs shallow copies, how do you even draw the lines, where are the objects?).

And the major philosophical flaw in the const vs. non-const distinction is that to make a strict separation you have to move everything mutable into constructor calls (for the most part, not getting more into the weeds of C++). Which is very awkward, it's a real tradeoff you need to be aware of. I realized only after playing these games for a long time what a waste of time it is and how much complexity it creates.

▲pif 3 hours ago | parent | prev [-]

> you have to deal with RAII

If you find that RAII is a problem, I pity how poor a programmer you must be...

▲jstimpfle 3 hours ago | parent [-]

You must be very experienced to be so judgemental! But maybe ask the many billions of voxels that get tested per second on my multithreaded and SIMD'ed cutting simulation.

▲kccqzy 2 hours ago | parent [-]

C++ is the best language to write multi-architecture SIMD without relying on compiler magics like autovectorization. It gives you enough tools to define zero-cost abstractions to make SIMD nice.

▲kccqzy 3 hours ago | parent | prev [-]

So what? You like <vector>, and make it the only allowed include. Write all other type safe generic data structures by hand using C++ syntax. Problem solved. In fact many old codebases migrated from C already has their own implementations of strings and vectors and hash tables, so these projects can totally forbid the C++ standard library versions in favor of their own versions, and only pull in <type_traits> for easier type safe generic data structure programming.

▲accelbred 4 hours ago | parent | prev [-]

You cant touch C++ without bringing the object lifetime stuff in. And unlike strict aliasing, theres no flag to turn it off.

▲jeffbee 4 hours ago | parent [-]

Object lifetime is the entire point of C++ and it solves ~100% of the emergent flaws in C programs.

▲accelbred 4 hours ago | parent [-]

I was just dealing with this: https://bugs.gentoo.org/show_bug.cgi?id=974323.

Also std::start_lifetime_at is a hack and ive seen nobody using it in all the placed where it aught to be used.

If optimizing based on object lifetimes could be turned off, itd be turned off everywhere for hardening like strict aliasing is.

▲jeffbee 4 hours ago | parent [-]

In my personal opinion, the fix[1] for that issue clearly implicates C-style habits polluting a C++ code base. No right-thinking knower of C++ initializes objects with memset! Also I believe that -Wall would have flagged that, and I know for certain that cppcoreguidelines-init-variables + cppcoreguidelines-pro-type-member-init would have flagged it.

1: https://github.com/llvm/llvm-project/commit/905a88b923433eb8...

▲ 2 hours ago | parent [-]
[deleted]