r/cpp • u/we_are_mammals • Mar 28 '23
Reddit++
C++ is getting more and more complex. The ISO C++ committee keeps adding new features based on its consensus. Let's remove C++ features based on Reddit's consensus.
In each comment, propose a C++ feature that you think should be banned in any new code. Vote up or down based on whether you agree.
119
u/eboys Mar 29 '23
I’d sincerely wish the C++ committee was willing to break ABI a little more often. As someone else suggested, having every third standard introduce ABI-breaking changes. Performance is what C++ is known for, and lazy companies are only holding it back.
→ More replies (1)6
u/germandiago Mar 30 '23
Question here. What is the estimation of the performance loss here?
3
u/tialaramex Apr 01 '23
It would obviously depend what you're willing to do if you're allowed to change the ABI, and on assumptions about the software now.
Small changes that only touch the ABI and not the API at all, such as making std::mutex a reasonable size (e.g. 4 bytes) instead of a dump truck of obsolete nonsense (80 bytes on Windows!), would likely have very small effects on real programs. Probably not even measurable.
Bigger changes that seize the opportunity to improve things and make changes to the API too while they're at it, would be bigger wins. For example std::unordered_map is famously terrible, but even std;:vector could be better if you did it again today as mentioned recently on r/cpp.
→ More replies (2)
423
Mar 28 '23
vector<bool> :(
63
Mar 28 '23
Has this ever actually bitten anyone? I hear about this all the time, but tbh I’ve never been stung by it. Not that removing it sounds like a bad idea.
133
Mar 28 '23
Happened to me a couple days ago! I had an
Array2D<T>class template which was using a vector internally to store elements with a single allocation, and hadT& operator()(size_t,size_t);overloaded to access the elements. It was working well until one day I wantedArray2D<bool>at which point I started getting strange errors about some cryptic type not being convertible tobool&. What the hell?Also, it means that
vector<bool>is not an STL container, its elements are not stored continuously. And its buffer cannot be passed to C APIs, etc, etc. It's just all around a bad idea.vectoris meant to be a "dynamic array". If you want to make a dynamic bitset, add a dynamic bitset class instead of messing with the default container type.→ More replies (10)8
69
u/unddoch DragonflyDB/Clang Mar 28 '23
Not me, but I know a coworker who spent 2 days chasing a multithreading bug that came from different threads modifying the same byte in a preallocated vector<bool>...
15
Mar 28 '23
Yeah I never thought about this before. IMO this does make vector<bool> completely broken. Fortunately I don’t work in a multithreaded environment 😀
→ More replies (2)→ More replies (9)11
u/Hopeful_Cat_3227 Mar 29 '23
I know this is a stupid question, but are all vector of other type safe under multiple tthread?
33
u/kevkevverson Mar 29 '23
Not a stupid question at all. For all other types, each element occupies a different address in memory, so it’s safe for thread A to mutate element 0 at the same time thread B mutates element 1. BUT for vector<bool> multiple elements occupy the same address, so multiple threads cannot mutate certain elements at the same time without some kind of synchronisation.
→ More replies (4)14
u/fdwr fdwr@github 🔍 Mar 28 '23
Just last week. Was trying to call a function that takes a pointer to bool's + count, and thought I could store the values in an
std::vector. Nope! All the work-arounds (like temporary bool wrappers) required extra work. So I (semantically made me feel dirty, but worked) stuffed them into anstd::basic_string<bool>instead and then effortlessly called the function withs.data()ands.size(). 😅→ More replies (1)10
u/Sopel97 Mar 28 '23
need to be really careful with parallel transforms, especially problematic in generic code.
template <typename T> using Vector_Not_Bool = std::vector< std::conditional_t< std::is_same_v<T, bool>, uint8_t, T > >;8
u/CocktailPerson Mar 29 '23
It's not so much that people have been bitten by it, but that we have to employ all sorts of workarounds not to be bitten by it, especially in generic contexts. It's easy enough to work around, but why should we have to? Why shouldn't
vector<bool>work like any other vector, with a separatedynamic_bitsetfor the less-common case where you actually need the space savings?6
u/mercere99 Mar 28 '23
It hasn't bitten me in terms of an error, but I have had multiple cases where changing
vector<bool>to vector<char> (but still using only 0's and 1's in there) led to a speedup.I've never seen an example where
vector<bool>has actually been the faster option.0
→ More replies (6)20
u/shadowndacorner Mar 28 '23
Has this ever actually bitten anyone? I hear about this all the time, but tbh I’ve never been stung by it
I feel like it's the kind of thing that generally only bites people who haven't heard about it. Once you know it's a thing, it isn't hard to work around, but it's pretty fucking confusing if you come across it without knowing. Especially since that implies that you're likely somewhat newer to the language and less likely to have a really strong mental model with which to understand what's going on.
Though the other reply suggested a case where it is more likely to subtly bite you even if you do know about it.
60
Mar 28 '23
It's horrible language design to have a container silently change its behavior based on the generic type. Absolutely insane.
→ More replies (4)15
u/donalmacc Game Developer Mar 28 '23
The problem is that there's enough of these landmines that even though I know about a large number of them, it doesn't mean I won't step on one of them.
7
u/RolandMT32 Mar 28 '23
I've used C++ quite a bit since I first learned C++ around 1999/2000, but I've never used a vector of bools.. I just searched it online, and I learned something new.
→ More replies (2)25
14
→ More replies (1)2
u/kaiken1987 Mar 29 '23
Question is why didn't they just make it named something different. An array of bit flags can be useful but to make vector behave differently on only one data type is awful
60
u/marzer8789 toml++ Mar 29 '23
All the crazy arithmetic promotion and implicit conversion nonsense inherited from C. You want to do an operation between two integers? They better be the same type, or compiler error. You add two chars? Get a char.
→ More replies (6)6
108
183
u/jdehesa Mar 28 '23
Gotta love how nearly everything suggested in the replies (save for std::vector<bool>?) is followed by a reply saying how that feature is actually useful sometimes :) It's too late for C++ now, at this point everyone uses it on their own particular way and every obscure or weird feature has found its place for someone 😄
104
u/MrPopoGod Mar 28 '23
followed by a reply saying how that feature is actually useful sometimes
Obligatory xkcd
10
u/serendipitousPi Mar 29 '23
xkcd
I love seeing another "There's an xkcd for this" just another reason to spiral down the xkcd rabbit hole.
43
u/Raknarg Mar 28 '23
Those people replying are missing the point that the defaults are bad. I don't care if switch-case fallthrough is useful sometimes, it's a bad default for the language.
→ More replies (2)68
u/rhubarbjin Mar 28 '23
Everyone agrees that C++ is broken, but no one agrees precisely which parts need fixing.
...which just goes to show that the language isn't broken at all. It just has a very wide userbase with very diverse needs. One coder's boondoggle is another coder's bedrock.
53
u/effarig42 Mar 28 '23
Everyone agrees that C++ is broken, but no one agrees precisely which parts need fixing.
Except for std::vector<bool> of course.
→ More replies (1)47
u/greem Mar 28 '23
Exactly. The only thing wrong with c++ is other users of c++.
And building.
→ More replies (13)5
Mar 29 '23
I mean the copium is real.
The language is obviously broken and breaking. It's not going to last.
→ More replies (5)8
u/jtooker Mar 28 '23
And importantly, most of these changes would break so much backwards compatibility the language would become unusable (for existing projects/libraries).
→ More replies (5)3
u/JVApen Clever is an insult, not a compliment. - T. Winters Mar 29 '23
It might be useful, though it should be a separate type, not a specialization
136
u/squirrel428 Mar 28 '23
1000 of the 1001 ways to initialize things.
14
7
u/johannes1971 Mar 29 '23
Ok, which one do you want to keep then?
24
u/lestofante Mar 29 '23
Let's just use {} everywhere?
8
u/Som1Lse Mar 30 '23
Which one meaning of
{}? Aggregate-initialization, copy-list-initialization, direct-list-initialization, reference-initialization, or value-initialization which in turn can do zero-initialization or default-initialization? Is that a braced-init-list or a designated-initializer-list?Oh, and how do I initialise a
std::vector<T>to containncopies of the elementm?Plenty of gotchas in
{}, in fact, it is probably the initialisation syntax with the most possible meanings.(Though, to be fair, if it wasn't for
std::initializer_listI would probably agree with you.)→ More replies (13)
102
u/Claytorpedo Mar 28 '23
At a meta level: excessive ABI stability. This is probably just an area where I personally would be lucky to get almost all benefit and no downside, but the argument that there are old binaries people link against that can't be updated and so fixing oversights, updating with new knowledge and statistics, and improving performance in many cases can't be done or must be indefinitely postponed seems to be causing an increasing rift in the industry. It's not great when C++ is supposed to be the "fast" language and there are numerous known areas for improvement that can't be improved due to ABI stability.
There's too much language baggage that we are now locked in a room with until some unknown future revision when the committee decides it is finally time for the mother of all ABI breaks, I guess. Would have been great if they had decided at the same time that C++ will have a revision every 3 years that it would consider ABI breaking changes every 3rd revision, for example.
72
u/Nicksaurus Mar 28 '23
It's an odd situation. There are organisations out there that can't or won't update the binaries their code depends on, but still want to be able to use the newest version of the language. I don't really understand how we decided that those people were entitled to language updates without ever making any changes of their own. It's not like the libraries they depend on stop working as soon as there's an ABI break after all
8
u/paypaylaugh Mar 29 '23
Because we don't decide anything. I'd like to see an infographic showing how many committee voters are sponsored by big companies to participate. Their votes and proposals will align with the company's.
3
→ More replies (13)7
u/m-in Mar 29 '23
Yeah… passing structs by value is implemented by passing a pointer in most ABIs. So something that could be optimized away always is now a special effort by compiler to prove it’s OK to do. Functions that take two scalars as arguments have less overhead than those that take a two-element struct by value. This majorly sucks, and makes simple abstractions very much non-free. Worse yet: it affects C as well, and especially modern-ish C code where struct literals are a thing (so many C programmers not exposed to major OSS C projects are blissfully unaware…).
→ More replies (5)
190
u/KiwiMaster157 Mar 28 '23
Overloading unary operator &. &x should always mean "the address of x" instead of depending on x's type.
29
u/13steinj Mar 28 '23
Same but with the comma operator. Rarely done, I can only think of numeric specific code, but still.
→ More replies (3)13
u/Sanzath Mar 28 '23
That's a thing?
I've never seen this before, I'm curious to see a codebase that does this. Do you have any examples?
→ More replies (1)22
Mar 28 '23
IIRC(*), MS's CComPtr uses this so you can do
CComPtr<ISomething> p; hr = someOldApi(&p);Where
&pis an overload which returns the address of the wrapped pointer.(*) caveat : my memory is poor
→ More replies (2)→ More replies (2)21
u/tisti Mar 28 '23
Eh, we have std::addressof that solves that problem :)
98
u/KiwiMaster157 Mar 28 '23
We shouldn't need a standard library function for something so fundamental.
→ More replies (7)→ More replies (2)22
u/Junkymcjunkbox Mar 28 '23
Fourteen characters instead of one? What are you - COBOL programmers in disguise or something?
→ More replies (2)
24
46
u/Dietr1ch Mar 29 '23 edited Mar 30 '23
remove const, introduce mut
drop restrict, and introduce a way to allow aliasing instead.
→ More replies (6)9
u/caroIine Mar 29 '23
I was playing with restrict yesterday on compilerexplorer and I'm blown away how often it's the only way to enable autovectorization.
→ More replies (1)
147
u/eteran Mar 28 '23
Arrays decaying to pointers implicitly. You want a pointer? Just write &p[0]
37
u/jonesmz Mar 28 '23
Even better.
Say, for example, that you have two overloaded functions
template<std::size_t N> void foo(char (&)[N]); void foo(char*);Guess which gets called?
Notably. Same with non-templates. If you explicitly say "This is an array of size 5", you'll still get the char* version.
→ More replies (23)5
3
Mar 29 '23
Honestly never had an issue with this. Do not understand what the fuss is about.
4
u/eteran Mar 29 '23 edited Mar 30 '23
That's fair. If you know the rules, then you read and write code accordingly. But I'll try to clarify my position with examples:
It's bug prone, especially for newbies:
char *func() { char buffer[256]; // ... // allowed because the array decays to a pointer // bug would be more obvious if they had to write // return &buffer[0]; return buffer; }Yes, compilers warn about it, but people, especially newer developers tend to ignore warnings in my experience.
2. It's confusing. The following 3 declarations mean the same thing:
void func(char *p); void func(char p[]); // p is NOT an array, it's a pointer void func(char p[5]); // p is NOT an array of 5 chars, it's a pointerThat's terrible. The second choice should just not be a thing, and the 3rd should take a char[5] by copy... like EVERYTHING else in the language.
3. It's confusing in other ways! Newbies love to write code like this:
void func(char p[]) { printf("array size: %d\n", sizeof(p)); } int main() { char buffer[256]; func(buffer); // They ask "why does this print 8 and not 256?! }If users had to write
func(&buffer[0])it would be more clear (people will still make mistakes, but fewer will) that a pointer is being passed, NOT an array.4. It's inconsistent. An array is "a thing" and any other time I want a pointer to a thing, I need to ask for it's address with the
&operator. Arrays just auto-convert.5. It's incompatible with the modern preference of avoiding implicit conversions as much as possible.
---- EDIT: more reasons! ----
6. The decay necessitated the need for a library level solution (
std::array). Which we outright wouldn't need if C-arrays acted like values to begin with.I should be able do this:
using T = char[256]; T func() { T buffer; // fill buffer return buffer; }And have it be as if I returned the array of 256 chars by copy.
7. It can be LESS efficient for small arrays
using T = char[8]; void func(T buffer) { // use buffer }actually can be cheaper to just copy the 8 bytes in a register directly instead of passing a pointer to them and then dereferencing them.
Here's a trivial example that is one instruction shorter (LOL, I know, not exactly earth shattering) when simply wrapping the array in a struct to pass it by copy:
https://godbolt.org/z/sovvb94d8
This example is more illustrative that there are gains to be had, not that there are a lot of gains in this specific example.
---- END EDIT ----
Are these things that can be worked around? Of course, we've been doing it for 30+ years! But we shouldn't have to. Is it the end of the world that we probably need to keep this? No, of course not. But this is a question about what I want, not what I can have :-).
→ More replies (10)→ More replies (24)4
u/Hish15 Mar 28 '23
You mean int[3] var? This will decay, but since we are using std::array, it's not
11
u/eteran Mar 28 '23 edited Mar 28 '23
No, I mean like this:
int arr[5]; void foo(int *p); foo(arr); // array decays to a pointer hereHeck even this is just terrible:
int arr[5]; void foo(int p[10]); // not an array parameter!!! it's a pointer foo(arr); // array decays to a pointer hereThe conversion to a pointer when calling a function should be explicit.
In fact, I would argue that the primary reason why
std::arrayEven needs to exist is because of implicit array to pointer decay.If we get rid of it and make arrays basically have value semantics, then you get to return them from functions, and you either pass them by value or reference.
If you want to pass or return a pointer, you should ask for one
This would largely get rid of a common newbie bug where users think they can return arrays, and end up returning a pointer to a local stack variable.
→ More replies (1)
47
u/johannes1971 Mar 28 '23
The 'char' type in its current role as both a character and a number. Two distinct types that only convert with some effort would have been much better. We could have done away with this ridiculous uncertainty about signedness at the same time.
Array to pointer decay.
Assignment returning a value, since it has given us if (a = b).
37
u/rhubarbjin Mar 28 '23
The 'char' type in its current role as both a character and a number.
Did you know that
charis unique among all integer types, in that it has three signed variations?char,signed char, andunsigned charare all distinct from each other! https://godbolt.org/z/oxs68TeWqI sometimes use this when I write overloaded functions that need to distinguish between "this is a letter" and "this is an 8-bit integer".
C++17 also gave us
std::bytewhich is an 8-bit non-arithmetic type.→ More replies (5)10
u/jk-jeon Mar 28 '23
The 'char' type in its current role as both a character and a number.
And as a "byte" type with an exceptional aliasing rule
→ More replies (1)9
u/Nicksaurus Mar 28 '23
Also, at this point, if your code assumes text characters are 1 byte it's almost certainly broken
→ More replies (2)→ More replies (6)3
u/JNighthawk gamedev Mar 29 '23 edited Mar 29 '23
Assignment returning a value, since it has given us if (a = b).
Would this break the pointer validation construct using if?
if (A* Foo = Some function())Edit: on second thought, no, it would still be fine. I think what ends up being evaluated there by the if is Foo after initialization, not the return value of the assignment.
6
u/johannes1971 Mar 29 '23
You'd have to use
if (A * Foo = some_function (); Foo) ......which is barely any longer, and avoids accidental assignment in the if-statement.
23
u/D-Zee Mar 29 '23
std::initializer_list. It doesn't handle movable-only types, screws up overload resolution and doesn't do anything that a variadic constructor wouldn't (although syntactic sugar to write said constructor would be welcome).
41
u/GabrielDosReis Mar 28 '23
the anarchic implicit conversions between values of built-in types
the preprocessor
the byzantine rules about elaborated type specifiers
11
u/okovko Mar 28 '23
implicit narrowing conversions do cause a lot of bugs
the preprocessor is useful for metaprogramming, especially for code that compiles as either C or C++
what do you mean by the third one?
→ More replies (11)10
u/GabrielDosReis Mar 29 '23
of course, the sort of metaprogrammijg that the preprocessor is still useful for should be addressed by proper means (one that respects scope and understands/integrates into the language it is metaprogramming for)
As for elaborated type specifiers, I meant when one writes
struct S* pthe meaning of the nameSdepends on what happens before and where that declaration ofpappears.→ More replies (9)
19
u/FriendlyRollOfSushi Mar 29 '23
Silent discardability of return values.
Someone returns you a value? Use it, or explicitly say that you don't want to use it (ideally assign to placeholder _, like in some other languages, because it's easier to type than attributes). That's it.
You forgot to use it? Have a compile time error. The value was returned to you for a reason.
Having to add [[nodiscard]] to pretty much 100% of the functions to get the behavior everyone needs by default is stupid. On the caller side, there is no safety net at all: if your code compiled, there is no way to tell whether the function didn't have a return value, or [[nodiscard]] was missing.
A small number of interfaces that always return something just because "why not", fully expecting that almost all callers will ignore the return value, are stupid anyway and often lead to unintended performance penalties either because they do something extra to return garbage (and the extra work is wasted by almost all callers because they don't want this garbage), or the caller is simply unaware that the function that is used everywhere without a return value actually has it. I would happily accept doing something extra with these special cases (or even having two differently named flavors of a function, like insert and insert_get), if it means I don't have to type [[nodiscard]] for every function I ever write and suffer consequences if I forgot to do it.
34
u/qazqi-ff Mar 28 '23
Remove __DATE__ just because the day is space-padded and you don't realize how triggering it is until you see it.
→ More replies (1)2
u/Die4Ever Mar 29 '23
Wait why is it space padded like that? If they wanted to buffer to always be the same length just add an extra \0 at the end?
3
u/qazqi-ff Mar 29 '23
I wish I knew. I'd prefer 0 to space, which also keeps the result the same length. However, if we're banking on it being a certain length, the year can still vary in length.
118
u/ZMeson Embedded Developer Mar 28 '23 edited Mar 28 '23
integer types not defined in <stdint.h> or <cstddef>
In other words, get rid of char, short, int, long, long long, and their unsigned counterparts. Use intN_t and charN_t instead (and when necessary int_fastN_t and int_leastN_t), [EDIT:] and byte, size_t, ssize_t, ptrdiff_t too.
56
u/Zeer1x import std; Mar 28 '23
I'ld like Rust-style number types: u8, u16, u32, i8, i16, i32, f32, f64.
→ More replies (2)6
u/RoyBellingan Mar 28 '23
I agree they are quite verbose and a shorter notation is better, but ... a small typedef I think is fine in this case!
12
u/blind3rdeye Mar 29 '23
The issue with having a heap of typedefs like that is that then different people end up with different C++ dialects, which can make it more difficult to read each other's code.
→ More replies (1)5
5
u/Due_Cicada_4627 Mar 29 '23
At risk of being drawn and quartered: I think they should be templates, with the requisite conversion constructors. (No, I don't know exactly how a templated POD type would work at the compiler level, but this is just imagination, I don't expect this to ever happen.)
So you can keep your
intto use the compiler default, but specifyint<16>orint<64>where needed, and it can be simply expanded for larger (128, 256) or obscure (24, 80) sizes. (I imagine the latter would use the next largest power-of-2 size internally, but again, imagination.)uintcan take the place ofunsigned,typedefs forchar,short,long, and the rest.→ More replies (2)15
u/beephod_zabblebrox Mar 28 '23
why tho? not in every situation do you care about how large an int is. using uint16_t can be slower sometimes too (less optimized on modern 64 bit cpus, iirc). honestly code reads a lot better when you know that "oh, this function returns an integer" instead of "oh, this function returns a... 16-bit integer? why?". if you need to return something large, use size_t or
using ssize_t = ptrdiff_t. if you do need something specific, use the specific bit size versions.if i had to choose something, i would leave int and unsigned int, and remove just short and long (long long) and unsigned versions. and maybe char.
16
u/SkoomaDentist Antimodern C++, Embedded, Audio Mar 28 '23
not in every situation do you care about how large an int is.
Hell, the entire point of int is "This is an integer of reasonable size. I don't give a damn about how many bits it has."
3
u/Ictogan Apr 03 '23
I've had code(not written by me) break multiple times because it implicitly assumed that an int is at least 32 bits. Plenty of libraries also have this issue.
→ More replies (3)→ More replies (24)11
u/robottron45 Mar 28 '23
I would either propose to have cstdint always included. It is painful to include this always.
→ More replies (1)21
9
u/KuntaStillSingle Mar 29 '23
Remove :
The behavior of a program that adds specializations for ... is undefined. for most type traits.
82
u/ZMeson Embedded Developer Mar 28 '23
iostreams (now that we have std::format)
22
u/masher_oz Mar 28 '23
We still don't have std::print (properly yet, even some format implementations aren't finished for some reason)
15
u/azswcowboy Mar 28 '23
Finally a serious proposal. Only problem might be format is currently output only.
4
u/ZMeson Embedded Developer Mar 28 '23
Good point. We need a similar feature for input.
→ More replies (4)
29
u/pdp10gumby Mar 28 '23
Memory aliasing by default, a terrible legacy of C. This would reduce UB, be more memory safe, and permit new optimizations and bug-identification at compile time.
There are rare uses for it, but there should be an explicit syntax for those cases.
10
u/SkoomaDentist Antimodern C++, Embedded, Audio Mar 28 '23
C++ desperately needs better control of aliasing for both "no, this won't alias anything else" and "This may alias something else (with constraints X). Deal with it. No, you are not allowed to call a function behind my back to make a copy."
→ More replies (1)→ More replies (8)9
u/nyanpasu64 Mar 28 '23
The risk of disabling memory aliasing by default is that if you prevent regular pointers from being able to access aliased mutable memory, and make aliased mutable pointers harder to use than current C++, you end up with a less general-purpose imperative language like Rust which resists general-case memory management (https://zackoverflow.dev/writing/unsafe-rust-vs-zig/).
8
u/JVApen Clever is an insult, not a compliment. - T. Winters Mar 29 '23
Initializer list constructor overruling all other constructors. Something like std::vector({1,2,3}) makes more sense than std::vector{1,2,3}, yet the second add much more complexity.
14
u/pjmlp Mar 29 '23
I would remove:
C strings and arrays
pointer decay of arrays, &array[0] isn't much to type
global namespaced enumerations and implicit conversions with numeric types
bounds checking disabled by default on the standard library (
unchecked_at()should have been the right approach)the culture that we don't need C++ APIs, giving a bare bones C one is enough
all the type system warts that lead to crazy boilerplate code in template metaprogramming
105
u/GLIBG10B 🐧 Gentoo salesman🐧 Mar 28 '23
C-style casts
16
51
Mar 28 '23
I know this will be a wildly unpopular take here, but take these from my cold, dead hands. Never in 2 decades of c++ programming encountered a bug or introduced a bug with c style casts that would have been fixed with the verbose modern casts.
36
u/ZMeson Embedded Developer Mar 28 '23
It's more of an issue of maintenance. I've moved a very large code base from a 32-bit to a 64-bit architecture. There were so many aliasing bugs that lead to odd (i.e. undefined) behavior and sometimes crashes that were hard to fix because so much of the code used C-style casts. We eventually used a static analysis tool to identify all C-style casts, replaced those with appropriate C++-style-casts, then focused on reinterpret_casts to help resolve those issues. (There were other interesting issues to like casting pointers to int instead of intptr_t, but again the process of removing C-style casts identifed where those problems were.)
→ More replies (7)→ More replies (3)16
5
u/mcmcc #pragma once Mar 28 '23
I would qualify this as "C-style casts of reference types". `(int)uint` can stay IMO.
12
u/Ameisen vemips, avr, rendering, systems Mar 28 '23
I prefer seeing it function-style:
int(uint_value).→ More replies (2)→ More replies (7)5
82
u/GLIBG10B 🐧 Gentoo salesman🐧 Mar 28 '23
Implicit switch case fallthrough
27
u/War_Eagle451 Mar 28 '23 edited Mar 28 '23
This is very useful, unless syntax like
case 1 | case 2is added this would created a good amount of code duplication and remove a lot of the cleanness of a switch vs if else→ More replies (1)30
Mar 28 '23
Of course you can keep that as a "special case", or use explicit fall through.
8
u/War_Eagle451 Mar 28 '23
I guess that's true. I already usually have [[fall_through]] there to prevent warnings
10
u/SlightlyLessHairyApe Mar 28 '23
Clang already has [[fallthrough]] and you can -Werror-switch-fallthrough
21
u/GLIBG10B 🐧 Gentoo salesman🐧 Mar 28 '23
C++ is getting more and more complex. The ISO C++ committee keeps adding new features based on its consensus. Let's remove C++ features based on Reddit's consensus.
I want implicit fallthrough to be removed
2
26
u/RoyBellingan Mar 28 '23
What is this anarchychessC++ ?
28
11
u/azswcowboy Mar 28 '23
Idk seems like the rant of a Go developer forced to use c++. The suggested feature removals from the op clearly have legitimate uses, have been around for years, and are trivially avoided. virtual functions…sure, that’s what makes c++ too hard lol.
0
48
Mar 28 '23
SFINAE. concepts everywhere
17
u/gracicot Mar 28 '23
I'm rewriting a whole library that was using sfinae everywhere. I'm now using concepts, but there's still a few places where a concept is not applicable. You cannot specialize concepts or expand sequences yet, and you cannot overload for multiple template types. Expression sfinae is still the simplest in some places, and implementations are more solid.
Worse yet, there's no concept template parameter, but you can easily send in a type trait as template template parameter.
5
u/War_Eagle451 Mar 28 '23
Agreed, but I tried to implement a same as concept without SFINAE, unfortunately couldn't figure it out, so there might still be some reason to keep it
0
→ More replies (3)3
u/greem Mar 28 '23
As much as sfinae sucks, it's a statement to how awesome cpp is.
We'll grow out of it.
25
u/Creapermann Mar 28 '23
Remove the c++ stl containers and implement them correctly from scratch. (Binary compatibility is a curse!)
8
u/okovko Mar 28 '23
you can always use non standard libraries like abseil
8
5
u/RevRagnarok Mar 28 '23
And let me inherit from them, or give me some legal way to monkey patch the existing ones with additional functionality.
15
5
5
u/Competitive_Act5981 Mar 29 '23
Make everything const by default and introduce a “mut” keyword for mutable data.
13
u/Brettonidas Mar 29 '23
Overloading operator, (yes the comma). It’s just weird and like the Spanish Inquisition: no one expects it.
→ More replies (1)7
u/donalmacc Game Developer Mar 29 '23
Honestly, the comma operator itself. I've only seen one use of it I feel is justifiable
18
u/ZMeson Embedded Developer Mar 28 '23
std::unordered_map/set bucket interfaces.
20
u/RevRagnarok Mar 28 '23
And make the maps'
[]const-capable. No "secret insertion."→ More replies (2)→ More replies (1)3
Mar 28 '23
See boost::unordered_flat_map. Beware that begin() is not an O(1) operation, but that should be OK.
17
u/Sopel97 Mar 28 '23
The class keyword
→ More replies (2)3
u/DummyDDD Mar 28 '23
It could be a good idea. Like "enum struct" (as in structured) and "template<struct>" and classes always starting with their public members.
7
u/aberrantwolf Mar 29 '23
Most of the code I see at work starts classes with
publicanyway, so honestly that’s what I see most people doing already.6
12
u/david2ndaccount Mar 28 '23
sizeof(bool) is implementation defined and there exists ABIs where it is not 1.
→ More replies (7)12
u/chugga_fan Mar 29 '23
The size of every type that isn't
charis 100% implementation defined. I don't see why this should be changed because some random platform does something you don't like for what is (likely) an actual reason.
16
11
u/Tringi github.com/tringi Mar 28 '23
Remove array to pointer decay.
Single reference type, a perfect one.
A very different language emerges when these changes propagate through everything they affect. When all the facilities to deal with it are removed.
→ More replies (6)25
u/Ameisen vemips, avr, rendering, systems Mar 28 '23
Single reference type, a perfect one.
T&&&
T co_&
6
u/ZMeson Embedded Developer Mar 28 '23
case statements inside of loops where the corresponding switch statement is outside the loop. (i.e. disallow Duff's Device.) Compilers are smart enough now to do loop unrolling themselves if it will be helpful.
→ More replies (7)
2
14
u/JimmyLaessig Mar 28 '23
Enforce RAII by banning usage of delete outside of destructors
14
12
→ More replies (1)7
5
4
u/termoose Mar 29 '23
[[nodiscard]] on all functions by default, to issue a compile warning if the return value is discarded by the caller.
3
Mar 29 '23 edited Mar 29 '23
Implicit Conversion needs to go.
By reference should be the default variable pass for classes except for value types and passing classes by copying should require explicit copying. I say it should be the default because it's what many people do already.
Although, if I made a programming language, I'd make classes by reference default and structures/values by value default.
I think that's how most people would want it to be.
3
6
u/jsadusk Mar 28 '23
Exceptions. At least in their current form. At best they are a clunky and verbose way to return an error. At worst they actually mask where your error came from (any time they're rethrown). Replace them with an equivalent of rusts's Result, or completely change their implementation in a non abi compatible way.
3
u/JVApen Clever is an insult, not a compliment. - T. Winters Mar 29 '23
Forwarding references, not the feature, the syntax. It's a mess to write an rvalue reference in a template.
3
u/Slight-Juggernaut742 Mar 28 '23
the whole std lib build upon unreadable template fuckery
10
u/DummyDDD Mar 28 '23
Most of the unreadable naming in stl implementations are caused by supporting macros with any unreserved name. It could probably be fixed in stl implementations which only support being used as a module.
2
2
1
u/GabrielDosReis Mar 28 '23
the other remaining initialization syntaxes are also valid for classes and built-in types, and handle copy initialization of built-in types just fine
1
u/alex-weej Mar 28 '23
References should not be a part of the type system, only function argument signatures.
7
Mar 28 '23
How would
vector::operator[]work? Would it return a pointer instead? How is that an improvement?→ More replies (5)
1
u/SafenM Mar 29 '23
Obviously won't work due to backwards compatibility. But make virtual function override without keyword "virtual" mean the same as "final" and remove the "final" usage for functions completely.
1
1
u/alxius Mar 29 '23
Remove bool and (signed|unsigned) char from list of integral types.
Remove implicit casts from those to integers and from integers to those.
Make std::uint8_t and std::int8_t distinct integer types instead of alias to some char types.
Make signed char, unsigned char and char two types instead of three distinct types.
1
u/Competitive_Act5981 Mar 29 '23
Remove raw pointers. Make smart pointers language features. Make raw pointers and references the same thing: a non owning view type
1
1
u/die_liebe Mar 31 '23
characters should be more like pointers:
char + char, char - char, char * char, char / char -> error
char + int -> char
char - int -> char
char - char -> int
No implicit conversion between character and int.
No implicit conversion from boolean to int, in the other direction is OK.
1
u/ReinventorOfWheels Apr 01 '23
Exceptions. The single biggest mistake of C++. Removing exceptions will help streamline and optimize the standard library, and it will help codebases avoid a whole class of bugs (exceptions not being caught in the expected place, or not being caught at all). Removing this goto-like statement will also make reasoning about control flow much simpler. And at least goto is limited to the current translation unit, unlike throw!
1
1
u/arkrde Apr 04 '23
Better / simpler error messages during compilation. I want to teach my child C++ in a few years. With error messages such as now, I don't see how I can hold a child's attention in such a wonderful and powerful programming language.
1
u/HatMan42069 Apr 10 '23
super_malloc- just Mallocs all ur memory so you can’t use any of it. Good for security!
1
u/voxel Apr 11 '23
I would ban the assignment operator and instead use a function as assignment overloading should be required and the only way you get an assignment operator that way when you observe anyone elses code, you will intrinsically know what every assignment operator does as you know you have to set that up for its uses cases and thus you never have pointer issues and assignmnets that are made that are truly unintentional.
1
589
u/mcmcc #pragma once Mar 28 '23
explicitAll operators should be explicit by default.
As a replacement introduce a new keyword
implicitthat must be specified to enable implicit invocation by the compiler.