@@dmitriidemenev5258 Yeah - whilst its new. That won't last forever, it will either become deprecated ain its entirety, or run into the same problem eventually.
Thanks for posting this, i was gonna watch it, but read the comments and realized i don't need to be more confused than i am already. Getting into C++ in 2023.
What a clusterfuck of complexity. Holy shit. Legends has it that bjarne steoustrup created c++ to increase the demand of programmers as things were getting simpler.
things never were simpler. existing competitors of C++ were much harder and weren't even expert friedly: Ada , LISP, etc. Means existence of multiple dialects, catering to "genial developers" instead of an expert with a standard in hand, etc.
@@miyurosewood3837 Ada is much, much simpler than C++ and without all the fancy footguns included. Besides, ada was made for mission critical software, no one in the right mind does mission critical software in "modern C++", as the number of plane crashes would skyrocket. And yes, things were much much simpler in the old days of C, and still are for those of us who are blessed to still be working with C.
@@ian3084 A lot of C++ issues come from C compatibility, so even at the beginning of the language there was some older stuff to support. If the language is recreated without anything to support then it's sure that it won't be as complex as it is now.
seems to be the best way to avoid confusion is to keep the old basic initialization One of the advantages is readability, second is avoiding bugs After all, what are we messing with is merely INITIALIZATION Why waste so much time on such an issue
Initializer lists were a mistake. It was an introduction of a new literal type without any syntactic differentiation to indicate that it was a new literal type, and so the compiler has to guess from context. It's a lot like the "Is this a constructor call or a function declaration?" problem you got with parenthesis based initialization. They should simply have forbade = initialization for any type that wasn't initializer_list, then they could've just then said that ordinary C arrays have a built-in constructor from an initializer_list. And an = sign should be required for aggregate initialization from an initializer list.
Perl actually got hit by same curse during its evolution. Any language risks it. Now it's Python. Only very 'special" people know emember Ada, although it's still a tool for developing critical stuff. Many languages that claim they "are better than C++" are just too young to have those health problems. Maybe Oracle was right to reclaim their rights on Java and slap Microsoft's grabby hands.
@@EllAntaresC++ is slowly rediscovering what Ada has been doing over the last 40 years, so... Yay? It isn't cool if we look back at what other people have done, it's Not Invented Here so it's not good
Am I alone to find that taking {1,2} as a complex (other than by backward compatibility) is weird? If the construct was explicit, we would use instead {complex{1,2}, complex{3,4}} , which IMHO is the correct way to do it, for vectors and for arrays. Explicit is safer than implicit.
@AlexFromHowest std::complex was defined using C++ but it coud have been defined as well in C++ using explicit, just by adding a keyword. I believe people tend today to prefer using explicit and avoid implicit conversions as much as possible. Note that the language didn't had in his 98 version the operator conversion in his explicit form. This probes that things changed and that we believe it is better to add explicit in more cases. I would like to have a time machine and change this default as other defaults as non-const, ... we have today in C++. Unfortunately I have not one. This doesn't implies that I need to change of language. BTW, what language would you suggest me to use because of my desire to be more explicit?
@@botetescribavicentej.2326 it's not explicit vs implicit constructor syntax. It's that the initializer list syntax has been made universal as in it will call constructors too
11:40 That already exists in C++17 via template type deduction. std::initializer_list l = {42}; std::initializer_list l{42}; Both will automatically deduce type int.
It isn't C++ if it there is not a sharp edge. Committee only made things worse by differentiating between auto i1{42} and auto i2 = {42}. Luckily I wasn't an AAA zealot in the first place.
40:03 has missing curly brace ('}') - e.g. std::vector v05 = {{"1, "2", "3"}; // OK .... but since the slide was showing various levels of curly braces, and there was already {"1", "2"} shown as exampl, I guess I can assume this is {{"1", "2"}}. Just FYI
I don't care which is correct or which is because of what, I care only when I get an error, what should I do. C++ is way too complex. It's not worth the time any more.
"Somebody might think this expression does X" is NOT a reason to make it compile and do X. The less ways there are to do a thing in a language the better. How is that not completely obvious to the comittee?
C syntax combined with templated code and allowance to overload or hide are icebergs that break up this assumption. E.g., because this logic Python language can't have operator= syntax or a ++a operator , `++a` in Python means `a` with twice used unary + operator - it's impossible to use those at tokens due to single mindedness of so-called lazy parser .. instead very obscure function names are used for operator and operator syntax varies contextually.
How does std::initializer_list creep into auto i = {42}; There is no mention of type, so there is no constructor taking a std::initializer_list. I thought std::initializer_list was supposed to be a lightweight proxy for T[N], the latter being a language concept. So you have the language keyword `auto` just basically assuming std:: ? Isn't this blurring the line between language and library? This is bad. "xyz" is a char[4] i.e. a T[N] not a std::string. Should auto s = "xyz"; make x a std::string? Well, if auto i = {42}; is a std::initializer_list then why not???
I think because curly braces imply an initialiser list. I think of them as a literal. But then that's not always true. Interesting point though that this is the only case I can think of where a syntax implies something from the standard library.
yes, a lot of c++ programmers use python as a 2nd lang. see also Stroustrup's oft-quoted line about a smaller, safer lang struggling to arise out of c++.
@@YoloMonstaaa They could, should -- and hopefully will -- add the concept of "editions" that are orthogonal to compiler version. In Rust for example we seldomly have small breaking changes in a new edition, but since it's a new edition it's not _actually_ a breaking change. You can just continue using the old edition with the newest compiler In a sense this is just -std=c++## but less rigid
Backwards compatibility, use of the same symbols and syntaxes with varying meaning and an ironic fear of verbosity. Yes, this is the mess that is C++. It's really quite amazing how they have managed to patch things up for so long. How long can this continue, I wonder? Perhaps it's time to scratch some of the old peculiars for good. At least stop using it and stop showing it. There are newer mistakes too, such as auto, but let's leave that for another time.
it seems he's trying not to add const on the left hand side? the way i interpret almost always auto is just to try to never write the type on the left side, so i'm fine with: constexpr auto x0 = ...; const auto x1 = ...; auto x2 = ...; const auto &r0 = ...; auto &r1 = ...; const auto *const p0 = ...; const auto *p1 = ...; const auto p2 = ...; auto *p3 = ...; and then almost always `type{...}` (aside from, for example, specific std::vector constructors as he mentioned). i will admit though that i'm unsure of what the default should be for struct/class members since you can't use auto. `struct S { type var{...}; };` i guess?
Can someone tell us why int i = {42}; should work? IMHO, the issue with initializers shouldn't be not one. I believe the problem has been in letting an initializer list of on element be convertible to something with the same type as the element, as in the example above. I'm missing surely the good reason explaining why we needed to make the previous code correct.
It all boils down to consistency - if we have empty list considered useful - as it let us value-init without stating the type - on one hand, and on the other - multi value list, also considered useful, for obvious reasons, then one element list comes naturally, both in expectation and generic code like U a = {get(b)...};
If i understand correctly, you think this ` = {42}` is initializer_list of type int that being converted to int. AFAIK it's not like that. ` = {42}` is implicit initilaization, it will be initializer_list if the type not specified by using auto, `auto i = {42}; ` `int i = {42}; ` work because the implicity is part of the language, the explicit version will be `int i = int{42}; `. if you have class with 3 parameter constructor, the implicit vs explicit would be `type var = {1st, 2nd, 3rd} ` vs `type var = type{1st, 2nd, 3rd} ` with 2 parameter constructor: `type var = {1st, 2nd} ` vs `type var = type{1st, 2nd} ` and with 1 parameter constructor: `type var = {1st} ` vs `type var = type{1st} ` even without parameter `type var = {} ` vs `type var = type{} ` you can see the consistency with curly braces initialization.
@@YourCRTube Thanks for your replay. Maybe you are right and there is a good reason. For the generic code, would't the following be enought? U a{get(b)...}
@@JanuarAndaria Thanks for the precisions. Nevertheless, Why do I need to have an implicit version while I'm initializing explicitly a variable? Why do we need to write int i = {42}; or int i = int{42}; when int i{42}; works? Again, why do you want to initialize var using only an implicit constructor when you have already types type var? There is surely something I'm yet missing?
@@botetescribavicentej.2326 There is clear, decades-long, effort to support the assignment syntax be as viable alternative to construction calls and others. I personally am all for that, as I believe it is the most teachable and visually distinct way of introducing variables. This does not mean I will ever write int i = {42}; , but I appreciate the symmetry and consistency.
at 54:37 there's a line auto z = {0,8,15}; //OOPS: still std::initializer_list but isn't this the right way? how else would I use auto with initializer_list?
"What a clusterfuck of complexity." Indeed. How do people expect to really bother to LEARN this language as a new language if every new release brings new pitfalls and things people have to remember how to get right? As someone who regularly teaches C and soon C++ to new colleagues, this is a nightmare. I don't understand why the C++ grammar still allows FUNCTION DECLARATIONS within functions. Yes yes yes, C backwards compatibility, but who does that anyway? Declaring a function within a function. That's a code smell.
I'm really sad that something so ugly as initialization with curly braces even exists... For the sake that bad rules for the common-sense kinds of initialization that have been used up by the past. Now we should write code where C++ looks more and more different from other comparable languages because some rules from the past where bad. In German we used to write Mayonnaise, which is not obvious to write correctly at first, but it's very easy to remember and when you learn French in school it's the same word, because it's where Germans got the word from. And then they introduced a different form of writing, for the same thing, which is easier to get right at first, but harder in the long run. Majonäse... (And while researching my facts I discovered that recently this abomination was removed from the German language again, yeah) C++ is diverging from how you write the same thing in C, C#, Java... for no good reason but backwards compatibility and making all things the same without using your brain. Backwards compatibility over all.
I just hope C++ just fixes the rules and restores the common operators to their original meaning and gets rid of the piling up complexity. Be like Mayonnaise dudes!
Not quite. It is just a backward compatibility. Please don't forget that it is backward compatibility that can be considered as "redundant diversity". Simply because it is a diversity-difference between old and new.
Cool! This gives me a new interview question for prospective C++ developers. I'll show them the Abseil and core guidelines advice on initializers and ask their opinion. Any that choose the core guidelines will be offered a job doing HTML and Javascript -- no way they're getting anywhere near our C++ codebase. Real Programmers use equals signs! 😀 (and West const!)
@@ic6406 none of this will work. Use 'a' instead. And yes this sounds very stupid because one has *a and the other has 42 'a' s. C++ must make it mandatory to include '\0' inside the braces in case you use braces to initialise it. Something like this would make more sense. string s{42, 'a', '\0'} Because I don't see anything wrong with the constructor overload. Not appending a '\0' would mean it's a char[ ] . Don't you agree
This is the kind of stuff that makes me want to quit C++ forever
The endless attemps to square the circle
It's almost incredible how retro-compatibility always makes things worse over time.
Rust with its modules, HIR and no need for backwards compatibility with C make compatibility issues almost nonexistent.
@@dmitriidemenev5258 lol come back in 30 years and we'll talk about your shiny rust
@@dmitriidemenev5258 Yeah - whilst its new. That won't last forever, it will either become deprecated ain its entirety, or run into the same problem eventually.
"If you're lucky, you get a core dump"
"Always Auto Ampersand Ampersand" fucking slayed me.
Thanks for posting this, i was gonna watch it, but read the comments and realized i don't need to be more confused than i am already. Getting into C++ in 2023.
I'm more confused now than I was before
What a clusterfuck of complexity. Holy shit.
Legends has it that bjarne steoustrup created c++ to increase the demand of programmers as things were getting simpler.
things never were simpler. existing competitors of C++ were much harder and weren't even expert friedly: Ada , LISP, etc. Means existence of multiple dialects, catering to "genial developers" instead of an expert with a standard in hand, etc.
@@miyurosewood3837you really chose Ada as an example, huh?
@@miyurosewood3837 Ada is much, much simpler than C++ and without all the fancy footguns included.
Besides, ada was made for mission critical software, no one in the right mind does mission critical software in "modern C++", as the number of plane crashes would skyrocket.
And yes, things were much much simpler in the old days of C, and still are for those of us who are blessed to still be working with C.
49:02 I wouldn't call that a fix...
If I delete a constructor, I don't want it to be used, no matter how.
C++ is evolution and not intelligent design.
This is insane.
Would love to see a C++2, with all the backwards compatibility thing removed
C++++?
@@AnonYmous-tx2sc C+=2
@@AnonYmous-tx2sc ++C--
Why do you assume they/we can't mess that one up, just as fast?:p I think most of the problems come from the initial adoption of features.
@@ian3084 A lot of C++ issues come from C compatibility, so even at the beginning of the language there was some older stuff to support. If the language is recreated without anything to support then it's sure that it won't be as complex as it is now.
seems to be the best way to avoid confusion is to keep the old basic initialization
One of the advantages is readability, second is avoiding bugs
After all, what are we messing with is merely INITIALIZATION
Why waste so much time on such an issue
Yeah initialization must be as intuitive as possible
Initializer lists were a mistake. It was an introduction of a new literal type without any syntactic differentiation to indicate that it was a new literal type, and so the compiler has to guess from context. It's a lot like the "Is this a constructor call or a function declaration?" problem you got with parenthesis based initialization.
They should simply have forbade = initialization for any type that wasn't initializer_list, then they could've just then said that ordinary C arrays have a built-in constructor from an initializer_list.
And an = sign should be required for aggregate initialization from an initializer list.
C++ is like Perl then? :-)
Fifty shades of initialisation: what shade do you prefer? Please be explicit.
Perl actually got hit by same curse during its evolution. Any language risks it. Now it's Python. Only very 'special" people know
emember Ada, although it's still a tool for developing critical stuff. Many languages that claim they "are better than C++" are just too young to have those health problems. Maybe Oracle was right to reclaim their rights on Java and slap Microsoft's grabby hands.
@@EllAntaresC++ is slowly rediscovering what Ada has been doing over the last 40 years, so... Yay? It isn't cool if we look back at what other people have done, it's Not Invented Here so it's not good
This explains why learning c++ is so frigging hard.
Am I alone to find that taking {1,2} as a complex (other than by backward compatibility) is weird?
If the construct was explicit, we would use instead {complex{1,2}, complex{3,4}} , which IMHO is the correct way to do it, for vectors and for arrays.
Explicit is safer than implicit.
@AlexFromHowest std::complex was defined using C++ but it coud have been defined as well in C++ using explicit, just by adding a keyword. I believe people tend today to prefer using explicit and avoid implicit conversions as much as possible. Note that the language didn't had in his 98 version the operator conversion in his explicit form. This probes that things changed and that we believe it is better to add explicit in more cases.
I would like to have a time machine and change this default as other defaults as non-const, ... we have today in C++. Unfortunately I have not one. This doesn't implies that I need to change of language.
BTW, what language would you suggest me to use because of my desire to be more explicit?
@AlexFromHowest Why do you want I change of language? Sorry, I cannot do it for the project I'm working on.
@AlexFromHowest Sorry, I forgot.
@@botetescribavicentej.2326 it's not explicit vs implicit constructor syntax.
It's that the initializer list syntax has been made universal as in it will call constructors too
The Legend (=, Thank you so much Mr Nikolai! I love your books, thank you!
11:40 That already exists in C++17 via template type deduction.
std::initializer_list l = {42};
std::initializer_list l{42};
Both will automatically deduce type int.
not the same thing, he used different syntax :P
Stay positive and let that smile light your way.
IMHO initialization with "=" should do the same exact thing as without "=". The fact that it doesn't is a bug!
make initialization with "=" default, let compiler decide when optimization kicks in
It isn't C++ if it there is not a sharp edge. Committee only made things worse by differentiating between auto i1{42} and auto i2 = {42}. Luckily I wasn't an AAA zealot in the first place.
40:03 has missing curly brace ('}') - e.g. std::vector v05 = {{"1, "2", "3"}; // OK .... but since the slide was showing various levels of curly braces, and there was already {"1", "2"} shown as exampl, I guess I can assume this is {{"1", "2"}}. Just FYI
Uncover future insights with an exclusive interview featuring Binance’s CEO
I guess this mess even confuses committee members
Heads up: crucial information about refunds
I don't care which is correct or which is because of what, I care only when I get an error, what should I do. C++ is way too complex. It's not worth the time any more.
"Somebody might think this expression does X" is NOT a reason to make it compile and do X. The less ways there are to do a thing in a language the better. How is that not completely obvious to the comittee?
C syntax combined with templated code and allowance to overload or hide are icebergs that break up this assumption. E.g., because this logic Python language can't have operator= syntax or a ++a operator , `++a` in Python means `a` with twice used unary + operator - it's impossible to use those at tokens due to single mindedness of so-called lazy parser .. instead very obscure function names are used for operator and operator syntax varies contextually.
It's official: essential details about refunds
How does std::initializer_list creep into auto i = {42}; There is no mention of type, so there is no constructor taking a std::initializer_list. I thought std::initializer_list was supposed to be a lightweight proxy for T[N], the latter being a language concept. So you have the language keyword `auto` just basically assuming std:: ? Isn't this blurring the line between language and library? This is bad. "xyz" is a char[4] i.e. a T[N] not a std::string. Should auto s = "xyz"; make x a std::string? Well, if auto i = {42}; is a std::initializer_list then why not???
I think because curly braces imply an initialiser list. I think of them as a literal. But then that's not always true.
Interesting point though that this is the only case I can think of where a syntax implies something from the standard library.
that why rust does not have overload and constructors have be name like createFromMem, createFormFile.
maybe the ultimate goal of c++ developers is to make it as simple as python and still keep the same performance as now
yes, a lot of c++ programmers use python as a 2nd lang. see also Stroustrup's oft-quoted line about a smaller, safer lang struggling to arise out of c++.
Modest proposal: Introduce new keyword 'let', follow uniform pattern 'let x = "
Adding a new keyword would be a breaking change to the language, breaking all code that uses 'let' as a variable or class name.
@@YoloMonstaaa They could, should -- and hopefully will -- add the concept of "editions" that are orthogonal to compiler version. In Rust for example we seldomly have small breaking changes in a new edition, but since it's a new edition it's not _actually_ a breaking change. You can just continue using the old edition with the newest compiler
In a sense this is just -std=c++## but less rigid
mov x, expression
x := expr;
So Pascal :)
There are over 9000 ways to initialize in c++ lol
Behind the scenes: Binance CEO shares insights into future developments in an exclusive interview
Backwards compatibility, use of the same symbols and syntaxes with varying meaning and an ironic fear of verbosity. Yes, this is the mess that is C++. It's really quite amazing how they have managed to patch things up for so long. How long can this continue, I wonder? Perhaps it's time to scratch some of the old peculiars for good. At least stop using it and stop showing it. There are newer mistakes too, such as auto, but let's leave that for another time.
Why would you need the static_cast when using auto& and auto&& though? (26:57)
it seems he's trying not to add const on the left hand side? the way i interpret almost always auto is just to try to never write the type on the left side, so i'm fine with:
constexpr auto x0 = ...;
const auto x1 = ...;
auto x2 = ...;
const auto &r0 = ...;
auto &r1 = ...;
const auto *const p0 = ...;
const auto *p1 = ...;
const auto p2 = ...;
auto *p3 = ...;
and then almost always `type{...}` (aside from, for example, specific std::vector constructors as he mentioned). i will admit though that i'm unsure of what the default should be for struct/class members since you can't use auto. `struct S { type var{...}; };` i guess?
Can someone tell us why
int i = {42};
should work?
IMHO, the issue with initializers shouldn't be not one. I believe the problem has been in letting an initializer list of on element be convertible to something with the same type as the element, as in the example above.
I'm missing surely the good reason explaining why we needed to make the previous code correct.
It all boils down to consistency - if we have empty list considered useful - as it let us value-init without stating the type - on one hand, and on the other - multi value list, also considered useful, for obvious reasons, then one element list comes naturally, both in expectation and generic code like U a = {get(b)...};
If i understand correctly, you think this ` = {42}` is initializer_list of type int that being converted to int. AFAIK it's not like that. ` = {42}` is implicit initilaization, it will be initializer_list if the type not specified by using auto, `auto i = {42}; `
`int i = {42}; ` work because the implicity is part of the language, the explicit version will be `int i = int{42}; `.
if you have class with 3 parameter constructor, the implicit vs explicit would be
`type var = {1st, 2nd, 3rd} ` vs `type var = type{1st, 2nd, 3rd} `
with 2 parameter constructor:
`type var = {1st, 2nd} ` vs `type var = type{1st, 2nd} `
and with 1 parameter constructor:
`type var = {1st} ` vs `type var = type{1st} `
even without parameter
`type var = {} ` vs `type var = type{} `
you can see the consistency with curly braces initialization.
@@YourCRTube Thanks for your replay. Maybe you are right and there is a good reason.
For the generic code, would't the following be enought?
U a{get(b)...}
@@JanuarAndaria Thanks for the precisions. Nevertheless,
Why do I need to have an implicit version while I'm initializing explicitly a variable?
Why do we need to write int i = {42}; or int i = int{42}; when int i{42}; works?
Again, why do you want to initialize var using only an implicit constructor when you have already types type var?
There is surely something I'm yet missing?
@@botetescribavicentej.2326 There is clear, decades-long, effort to support the assignment syntax be as viable alternative to construction calls and others. I personally am all for that, as I believe it is the most teachable and visually distinct way of introducing variables. This does not mean I will ever write int i = {42}; , but I appreciate the symmetry and consistency.
47:01 or slide 46: Why is v05 accepted and v07 is not?
nobody knows man, it's pretty magical
I think v05 is syntatically wrong, there is a missing braces
at 54:37 there's a line
auto z = {0,8,15}; //OOPS: still std::initializer_list
but isn't this the right way? how else would I use auto with initializer_list?
i guess making it not compile at all would be better way
Too many ideas on how to keep C++ relevant to modern coding coming to bear.
"What a clusterfuck of complexity." Indeed.
How do people expect to really bother to LEARN this language as a new language if every new release brings new pitfalls and things people have to remember how to get right?
As someone who regularly teaches C and soon C++ to new colleagues, this is a nightmare. I don't understand why the C++ grammar still allows FUNCTION DECLARATIONS within functions. Yes yes yes, C backwards compatibility, but who does that anyway? Declaring a function within a function. That's a code smell.
Are people actually using auto for variables out side loops?
Patrik Dahlström yes
Structured bindings
Of course, but only where the type of an expression is obvious.
@@superscatboy or, ironically, when it isn't obvious like std chrono or iterators. At least not as obvious when skim reading
you actually have no choice but to use auto in the case of e.g. lambdas
Thought this was going to be about RAII. Title still appropriate.
What's on the horizon? Exclusive interview with Binance's CEO reveals future insights
I'm really sad that something so ugly as initialization with curly braces even exists... For the sake that bad rules for the common-sense kinds of initialization that have been used up by the past.
Now we should write code where C++ looks more and more different from other comparable languages because some rules from the past where bad.
In German we used to write Mayonnaise, which is not obvious to write correctly at first, but it's very easy to remember and when you learn French in school it's the same word, because it's where Germans got the word from. And then they introduced a different form of writing, for the same thing, which is easier to get right at first, but harder in the long run. Majonäse... (And while researching my facts I discovered that recently this abomination was removed from the German language again, yeah)
C++ is diverging from how you write the same thing in C, C#, Java... for no good reason but backwards compatibility and making all things the same without using your brain. Backwards compatibility over all.
I just hope C++ just fixes the rules and restores the common operators to their original meaning and gets rid of the piling up complexity.
Be like Mayonnaise dudes!
❤️❤️❤️❤️❤️❤️❤️
GOOD
Everything is auto, so why need add auto in front of variables :) !!!
@7:00 no wonder I gave up on c++.
By the whims of a system error, the transaction was sent to an invalid email address.
The future revealed: exclusive interview with Binance's CEO
one word -> diversity at its madness' peak;
Not quite. It is just a backward compatibility. Please don't forget that it is backward compatibility that can be considered as "redundant diversity". Simply because it is a diversity-difference between old and new.
Sounds like parenthesis are the way to go.
Cool! This gives me a new interview question for prospective C++ developers. I'll show them the Abseil and core guidelines advice on initializers and ask their opinion. Any that choose the core guidelines will be offered a job doing HTML and Javascript -- no way they're getting anywhere near our C++ codebase. Real Programmers use equals signs! 😀 (and West const!)
but HTML and Javascript make heavy use of =
Here, take your first like, brother.
Tune into an exclusive interview with Binance's CEO for a sneak peek into future developments
We regret to inform you that the email was beyond reach due to a system error diverting a cryptocurrency transaction into the void.
Always use curly braces and apparently don't use = ever.
@@ic6406 none of this will work. Use 'a' instead. And yes this sounds very stupid because one has *a and the other has 42 'a' s. C++ must make it mandatory to include '\0' inside the braces in case you use braces to initialise it. Something like this would make more sense.
string s{42, 'a', '\0'}
Because I don't see anything wrong with the constructor overload. Not appending a '\0' would mean it's a char[ ] . Don't you agree
Business update: key details about refunds
This guy again. 😆
Did I hear std2? Yes please. And please fix vector initialization.
STD2 was dropped all together..
gosh please no