"BEST C++ CODE ever written" // Code Review

  Рет қаралды 126,943

The Cherno

The Cherno

Күн бұрын

Пікірлер: 650
@TheCherno
@TheCherno 13 күн бұрын
What do you think, should we keep going? 👇 Also don’t forget you can try everything Brilliant has to offer-free-for a full 30 days, visit brilliant.org/TheCherno . You’ll also get 20% off an annual premium subscription.
@orwazain
@orwazain 13 күн бұрын
Yes keep going we are learning, and this is our goal for 2025❤
@SouravChakraborty-y3w
@SouravChakraborty-y3w 13 күн бұрын
You are correct! Hence I've a request for you can you please make a playlist on SQL (using DB Browser with SQLite would be great). Please please help!
@stefankarlsson4652
@stefankarlsson4652 13 күн бұрын
Yes!
@akifimran9780
@akifimran9780 13 күн бұрын
Yes
@Hello_-_-_-_
@Hello_-_-_-_ 13 күн бұрын
Please continue on this project. I'm interested in how he set the memory size and if you could give us an example of using namespaces. Thank you
@not_ever
@not_ever 13 күн бұрын
I think we can all agree this is some of the C++ code ever written.
@toddeburch
@toddeburch 13 күн бұрын
@@not_ever lol W comment.
@381delirius
@381delirius 13 күн бұрын
some of the c++ code is all time
@adriantm8430
@adriantm8430 13 күн бұрын
It's almost C+++
@p1nek319
@p1nek319 10 күн бұрын
😂​@@adriantm8430
@chudchadanstud
@chudchadanstud 13 күн бұрын
Everyday I write the best code I've ever written. Everyday I also think yesterday's code is the worst I've ever written
@LG-qz8om
@LG-qz8om 13 күн бұрын
I'm always looking back at old code and thinking how i could have made it better. There is no such thing a Perfection.
@domenichelfenstein6584
@domenichelfenstein6584 12 күн бұрын
exactly how it should be! Unfortunately the intervals become longer. I'm now at a stage where I have to wait for about half a year to be disgusted by my own code.
@zelven6109
@zelven6109 5 күн бұрын
Everyday I also think yesterday's code is the best I've ever written
@nexovec
@nexovec 13 күн бұрын
Guy knows how to bait you into a code review 😆
@brdevll
@brdevll 13 күн бұрын
either that or bro is at the very peak of dunning-kruger effect
@nexovec
@nexovec 13 күн бұрын
@@brdevll Maybe he was happy about having written something he liked for the first time. We all have that one side project right? :D
@ty.davis3
@ty.davis3 13 күн бұрын
@@brdevllI think this video will abruptly shove him on his way down the steep hill of the dunning kruger effect
@brdevll
@brdevll 13 күн бұрын
@ty.davis3 yeah definitely lol hopefully he can climb back up again, this time with experience backing up the confidence :)
@ABaumstumpf
@ABaumstumpf 13 күн бұрын
Really good troll. "perfect code" and then "couldnt get naming consistent" followed by "that code i finished just now is old code". @@brdevll .... with that comment it seems you speak from experience?
@natescode
@natescode 9 күн бұрын
Junior: greatest code ever written Senior: absolute trash but it works, mostly.
@MapleLeavesInAutumn
@MapleLeavesInAutumn 13 күн бұрын
For me a 'using namespace' in a header file is absolutly forbidden.
@toddeburch
@toddeburch 13 күн бұрын
Agree-that using pollutes every consumer of the header!
@Grynjolf
@Grynjolf 13 күн бұрын
Nearly prefect
@scififan698
@scififan698 13 күн бұрын
indeed.. only total noobs do it. Type the f*ing namespace already. lol
@nextlifeonearth
@nextlifeonearth 13 күн бұрын
You can do it in your own namespace, to bring something from another namespace in yours, without polluting global namespace. I think that's the only exception though....
@vihannes3
@vihannes3 13 күн бұрын
Not just "for you", it's ABSOLUTELY forbidden
@cubemaster1298
@cubemaster1298 13 күн бұрын
26:00 There is actually a really OP keyword for this called 'consteval' that enforces a function call to be comptime and prevents runtime execution.
@ABaumstumpf
@ABaumstumpf 13 күн бұрын
"that enforces a function call to be comptime and prevents runtime execution." That is wrong: There is NO SUCH THING as compile-time in C++. Consteval only mandates that it is evaluated before the start of main. C++ can even be run as an interpreted language. that committee has been rather against any changes that would finally acknowledge even the existence of compilers.
@DiamondWolfX
@DiamondWolfX 13 күн бұрын
​@@ABaumstumpf What standard are you looking at? C++ talks about compilers all the time. It even has compile-time as its own complexity class.
@rickr530
@rickr530 13 күн бұрын
@@ABaumstumpf consteval requires the compiler to evaluate the function to a compile-time constant. I think your prejudices are out of date :)
@ABaumstumpf
@ABaumstumpf 12 күн бұрын
@@DiamondWolfX "C++ talks about compilers all the time." Yeah no it does NOT. You are mixing up people talking about C++ and the actual C++ specifications.
@ABaumstumpf
@ABaumstumpf 12 күн бұрын
@@rickr530 "consteval requires the compiler to evaluate the function to a compile-time constant." no, that is not what the standard says. "I think your prejudices are out of date :)" You might want to read the actual standard instead of just relying on DunningKruger.
@tedchirvasiu
@tedchirvasiu 13 күн бұрын
It's so good it's classified as C+++
@abgvedr
@abgvedr 13 күн бұрын
Its so C++ its basically A
@user-sl6gn1ss8p
@user-sl6gn1ss8p 13 күн бұрын
Surely you mean C++++
@mr.hashundredsofprivatepla3711
@mr.hashundredsofprivatepla3711 13 күн бұрын
@@user-sl6gn1ss8p So basically just C#
@boonyakornthanpanit7656
@boonyakornthanpanit7656 13 күн бұрын
@@user-sl6gn1ss8pdid you mean c#
@LG-qz8om
@LG-qz8om 13 күн бұрын
All Programming is basically Algebra. Beyond that is Calculus (constantly vars) The essence of Math Equations is this form: x^0 + x^1 + x^2 A) x^0 is Math (an unchanging value like Position) B) x^1 is Algebra (a changing value like Velocity) C) x^2 is Calculus (a continuously changing value like acceleration) Some people call this PID. I call it "012" One could do ALL math as [A,B,C] a simple array.
@TeslaPixel
@TeslaPixel 13 күн бұрын
"and used modern C++ features" looks like perfection is out of the window
@depralexcrimson
@depralexcrimson 13 күн бұрын
lmao yeah
@doodocina
@doodocina 13 күн бұрын
best c++ code should be written in extern "C" 😂😂
@ThisIsLiam-001
@ThisIsLiam-001 13 күн бұрын
If you wont adapt to the new features of C++ you’re better off, just going to rust
@sinom
@sinom 13 күн бұрын
​@@ThisIsLiam-001TBH modern C++ and rust aren't actually that dissimilar. Rust just has a lot less baggage, doesn't have a stable ABI and ofc has more (especially lifetime) safety features (which c++26 safety profiles aren't gonna magically fix no matter how much Stroustrup insists they will)
@skilz8098
@skilz8098 13 күн бұрын
There is no such programming language other than Binary itself, not even Assembly that would provide perfection. It's all a matter of knowing your tradeoffs!
@JasonGrace69
@JasonGrace69 13 күн бұрын
16:30 I took an audio programming class in college. I used msvc as my compiler (c++20), the professor used a compiler on Linux (c++11). I did not specify std:: before using size_t or for some other common integer types such as uint32_t Everything compiled fine on my machine but not the professors. The only issue in my project was that. I ended up being docked 10 points on the first assignment. I would say it's good practice to access the data types this way, as clearly outlined by the standard, because youll never know when you'll get burned. Edit to clarify: ANY warning or error in any of the projects (equivalent of /W4 on any compiler) resulted in a 10 point hit to the project grade, no matter how small. The class rules were just strict
@vlynst
@vlynst 13 күн бұрын
i mean that's pretty silly of him-it's best to be using the most recent compiler.
@Dienes
@Dienes 13 күн бұрын
@vlynst You either know what compiler you're writing code for, then you can do whatever works, or you don't know, then you stick with the standard. If OP knew his professor's compiler, they should have made sure the non-standard code worked with that. If they didn't know, then they should have stuck with the standard.
@vlynst
@vlynst 13 күн бұрын
@@Dienes except like, they could be sticking to the c++20 or c++15 standard and it may not compile either lol. idk, i'm assuming they didn't know what compiler they were targeting until afterwards, but definitely should have tested on that version it if they knew 🤷‍♀️ either way i think it's still silly to not have the latest standard for a college programming class instead of one from ~9 years ago though, lol.
@CaptTerrific
@CaptTerrific 13 күн бұрын
Also best practice to always compile on WSL before submitting projects, eh? ;)
@scififan698
@scififan698 13 күн бұрын
I would say it's a bad practice to use 'using' .. and even worse to not use it but also not specify the namespace and make it not compile. I think he took 10 points away because it clearly shows you have no clue what you're doing. look it up and soon you will know why this illustrates total beginner mode. and btw: rtfm
@DeGandalf
@DeGandalf 13 күн бұрын
11:28 If I remember Sebastian Lague's videos correctly, this is actually common practice for chess engines. I think it allows for some neat tricks when calculating moves, but I'm not entirely sure anymore. But I'd highly recommend his videos on that
@jollyjoker6340
@jollyjoker6340 13 күн бұрын
I've never seen a chess engine's code but this really looks like a structure where you can easily represent states with many pieces and add / subtract pieces.
@zoltankurti
@zoltankurti 13 күн бұрын
​@@jollyjoker6340it's standard in chess engines. Bitboards allow for very fast move generation for sliding pieces.
@criptych
@criptych 13 күн бұрын
As I remember it, from his video and other sources, bitboards help performance because they reduce most actions -- checking valid moves, moving pieces on the board -- to a handful of bitwise operations (effectively "SIMD" over the whole board) so even a lower-power CPU can process them very quickly. If the board were stored as an array of bytes instead, it would be much slower, needing multiple loops, conditions, and memory accesses per operation. The main tradeoff being that this representation can require extra work to encode and decode e.g. for notation or display, since the state of each square is stored across multiple values.
@AntiAtheismIsUnstoppable
@AntiAtheismIsUnstoppable 13 күн бұрын
@@criptych I mean... bitwise operations have been the very base for anyone who started on the C64 or VIC20. Every character, every sprite, was build out of bits, not bytes. Using bits instead of bytes is the most efficient way of using memory in many situations, where you have a fixed set of flags (or positions in a game). I have a blog where I use a 32 bit integer as a holder of 31 flags (because it is unsigned) for 31 different labels for a blog post. It is extremely much more efficient than storing a label in a byte or as a string, and because it is represented as a number, I can also use it for different languages for a label, as it is just a flag, a numerical value, not the label itself.
@ferinzz
@ferinzz 12 күн бұрын
@@AntiAtheismIsUnstoppable This kind of thinking is why I thought it odd that there was the mention of performance via bitmaps and then... A string to store the starting layout instead of a fixed-size u8 array. Or even some enums. Map the utf-8 value of the characters to an enum value. Maybe it's just the different way of thinking that I picked up due to writing in another language. Internals aren't strings, only use actual strings/cstrings for values which are going to be exposed to in the ui.
@ssgroast9640
@ssgroast9640 13 күн бұрын
This is the best comment i've ever written
@toddeburch
@toddeburch 13 күн бұрын
Agree. And I’ve followed your comments for a long time.
@ssgroast9640
@ssgroast9640 13 күн бұрын
@@toddeburch well congratulations as that's the best sneak insult I've seen
@toddeburch
@toddeburch 13 күн бұрын
@@ssgroast9640 haha actually I never even thought of that! You are brilliant!
@KurtVanBever
@KurtVanBever 13 күн бұрын
Honestly, I'm baffled at your bestness. Keep it up.
@TheCommunistRabbit
@TheCommunistRabbit 13 күн бұрын
This is the best complement you have ever gotten
@imphonic
@imphonic 13 күн бұрын
"modern C++ features" and "updated the C code to use object-oriented programming" aren't exactly a telltale sign of perfect code. Not that they're bad, but you don't need them to write good C++. All you need to write good C++ is "solve the problem you have given the constraints of the platform" as Mike Acton would put it. I agree that moving as much of the program as possible onto the stack is definitely a solid move.
@vlynst
@vlynst 13 күн бұрын
yeah but it was a banger sentence
@isodoubIet
@isodoubIet 13 күн бұрын
Mike Acton is definitely NOT who I'd be looking to if I wanted to learn how to write good C++.
@halfbakedproductions7887
@halfbakedproductions7887 13 күн бұрын
It's like those guidelines that say "Use Rust from now on" - you look at the 'Rust' code and it's just crummy old C++ shoehorned into a block marked as unsafe. But hey, it's 'Rust' - mission accomplished.
@ABaumstumpf
@ABaumstumpf 13 күн бұрын
The entire description and code are contradictory... you know, like a nice little troll.
@vlynst
@vlynst 13 күн бұрын
@@halfbakedproductions7887 (it takes 30x longer to build for the same output)
@showmeyourcritz321
@showmeyourcritz321 12 күн бұрын
0:54 "Best code ever written" does not go so well with "I don't know how to use a build system" 😂😂😂
@ladislavdobrovsky8826
@ladislavdobrovsky8826 6 күн бұрын
build systems are not the part of the mastery of the language itself ;)
@martinbennett9908
@martinbennett9908 12 күн бұрын
I imagined the email in the voice of Trump - "it's the best code ever written, no really, it's so powerful, it's really amazing, there's never been any code like this before"
@ProfShibe
@ProfShibe 12 күн бұрын
“No one writes better code, believe me”
@whukriede
@whukriede 11 күн бұрын
🎯Best comment ever.
@victoronwuhafua8464
@victoronwuhafua8464 2 күн бұрын
Believe me 👌
@Timm2003
@Timm2003 13 күн бұрын
constexpr = this value is known at compile time const = this value doesnt change, but its computed at runtime the compiler will probably be able to optimize it anyway but constexpr is what i use in such situations
@immanuellitzroth1905
@immanuellitzroth1905 13 күн бұрын
also passing constexpr args to constexpr functions allows compile time computation.
@dennisbuyse258
@dennisbuyse258 12 күн бұрын
But a const value can be a constant expression too. The way i understood it is const value: will be a constant expression if the assignment allows it. constexpr value: the assignment must be a constant expression. constexpr function: will be a constant expression if the arguments and function body allow it. consteval function: the arguments and function body must be constant expressions.
@Timm2003
@Timm2003 12 күн бұрын
@@dennisbuyse258 it would make sense to classify all const variables if possible as constexpr, but idk if the compiler can catch all cases
@dennisbuyse258
@dennisbuyse258 12 күн бұрын
@Timm2003 I don't think it depends on the compiler's implementation. It wouldn't make any sense to be able to assign a const value ("runtime") to a constexpr value (compile time) if the const value wasn't inherently a constexpr as well.
@Timm2003
@Timm2003 12 күн бұрын
@@dennisbuyse258 i meant if the compiler can detect that the value is contant at compile time.
@isodoubIet
@isodoubIet 13 күн бұрын
the std:: qualifier on sized arithmetic types will become more prevalent as people start using "import std" since the unqualified names are only brought by importing std.compat.
@isodoubIet
@isodoubIet 13 күн бұрын
(and yes, std::size_t, std::int64_t and friends are part of the standard, though you may need to include cstddef and cstdint to bring them in)
@BenjaminWheeler0510
@BenjaminWheeler0510 13 күн бұрын
Lol, hopefully within the next 100 years
@isodoubIet
@isodoubIet 13 күн бұрын
@ Hey it'll all be available in c++123
@MrEdrftgyuji
@MrEdrftgyuji 12 күн бұрын
There was an issue with some older versions of g++, that required the qualifier unless you include a C header.
@isodoubIet
@isodoubIet 12 күн бұрын
@ That's not an issue with gcc, I believe the standard itself specifies it that way. It's the same as the difference between cmath and math.h: the unqualified functions only get brought in if you include the latter
@zenith2808.
@zenith2808. 13 күн бұрын
It really is quite impressive how people have the courage to even make projects in the first place. I mean, this has been the case at least for me, but my perfectionism ends up getting the best of me and I can't even write code by myself. Looking for the "best practices" I end up going online and follow a tutorial to solve the problem for me instead of me flexing my own muscles. I think what makes a project complete for me is the fact that one actually took initiative for it. The rest is well, improved over an iterative cycle of trial and error where the programmer learns. There won't ever be "best [insert language] code ever written" because development is an iterative process, new technologies come out every single day. What matters more is the effort and what we can learn from others' code to incorporate into our own mindset. That's why I love this series so much Happy new year Cherno, thank you for this series and thank you for teaching me and this entire community skills that would've been harder to learn otherwise.
@Leonhart_93
@Leonhart_93 13 күн бұрын
Don't let "perfect" get in the way of "good" and "done".
@tapwater424
@tapwater424 13 күн бұрын
Perfectionism is a flaw, not a quirky personality trait. Just accept that all code is horrible and make whatever you want.
@zenith2808.
@zenith2808. 13 күн бұрын
@@tapwater424 Yeah, hacking is actually a pretty powerful technique
@canmetan670
@canmetan670 13 күн бұрын
I have the same problem. Time boxing learning and having deadlines fixes this. Can confirm
@gdcuaer4076
@gdcuaer4076 13 күн бұрын
My perfectionism 😢 Brooo chill.
@Bolpat
@Bolpat 13 күн бұрын
15:40 Using namespace is a big no-no in header files, except for very specific things if inline namespaces and namespace aliases don’t do the job or you can’t use them. Example: namespace my_namespace { using namespace other_namespace; …other sutff… } In his case, he doesn’t even need the "sv" literals, his array is constexpr initialized, so there’s nothing to gain there even hypothetically. The string_view objects are created at compile-time and they’re the same no matter if he uses sv or not.
@LG-qz8om
@LG-qz8om 13 күн бұрын
The WHOLE reason to add "namespace" to the C language was because everyone was creating Objects that had a function called "read", "write", or "print" and using so many other libraries meant you never knew whose Write you were calling. THAT'S the reason you don't use it inside library code. It is meaningless there. Its the main program where the reference becomes important.
@CaptTerrific
@CaptTerrific 13 күн бұрын
25:12 the overhead of using a map is literally insignificant next to the time allocated for the minimax. It's like optimizing buckling your seat belt before a drive from NY to Chicago
@Jeanpierrec19
@Jeanpierrec19 13 күн бұрын
And std::map uses a tree not a hash function in C++ usually. There is still a case to be made about cache locality. Also a lookup in an array is O(1) whereas in a map it may not be, probably is O(log n) which isn't as quick no matter how you slice it for this use case. The extra memory may be worth it here.
@CaptTerrific
@CaptTerrific 13 күн бұрын
@@Jeanpierrec19 I'm not saying an array wouldnt be faster, only that it's an odd place to optimize :) We'd have to see a full profiling, but I'd be surprised even if in a pointer-based tree didnt get fully cached - and since it's used each move, it probably wouldn't get evicted from L2 ever, but nearly certainly not from L3. But EVEN if it had to poll memory every time, that'd still take on the order of 100ns vs. the literal 10 SECONDS per move :D
@khatdubell
@khatdubell 13 күн бұрын
Or you could just use a switch for the 8 options that are hard coded and will never change during the execution of the program.
@salockin9515
@salockin9515 13 күн бұрын
I wrote code. I did what the tutorial I was following did, they were using C. I thought about using a std::unordered_map but I figured 128 bytes is so small it didn't matter.
@CaptTerrific
@CaptTerrific 13 күн бұрын
@ It's not a bad thing to do at all :) I was more commenting on Cherno focusing on the performance of the structure at all, when it is the furthest thing from a bottleneck - you did good!
@ciCCapROSTi
@ciCCapROSTi 13 күн бұрын
Pragmas are never added to the standard, pragma is by definition something OVER the standard, some compiler specific extension, even if it becomes a quasi standard. But sure, they COULD add some preprocessor directive to replicate the functionality. I just think they focus on making modules work, which makes header guards and pragma once unnecessary in the vast majority of cases. 20:40 I would definitely use some type that actually stores the chars locally, like a char[2] or an array. If this table is referenced a lot then I don't want to rely on the compiler to place the string literals close to each other, I want a guarantee that these 64*2 bytes are right next to each other and always hot in the cache. Also sparing a lot of indirection. Definitely continue, I wanna learn from this master of C++.
@marekdorobczynski1727
@marekdorobczynski1727 13 күн бұрын
I definitely wish to see continuation of this review, focusing on how the tree analysis has been implemented here incluing alpha-beta pruning and so on. BTW is this project taking advantage of multithreading ?
@salockin9515
@salockin9515 13 күн бұрын
I’m the author of the code. It doesn’t use multithreading, I plan to add it once in done adding some other features such as a transposition table and iterative search move ordering. And maybe some other stuff. It will probably be the last feature I add
@bogdyee
@bogdyee 13 күн бұрын
@@salockin9515 How high is the bot's elo? (Tested against other bots). I had mine at around 2000 without bitboard so I imagine yours must be much higher.
@commanderguyonyt0123
@commanderguyonyt0123 13 күн бұрын
Regarding the stringview array: It might be easier to make the array a single long string and index by i/2. This removes the layer of indirection imposed by stringviews/const char* and keeps the data near thereby keeping the memory 'hot' allowing better caching
@toddeburch
@toddeburch 13 күн бұрын
Another advantage of using a single string other than memory locality (for keeping memory hot) is you save the memory of all the null terminators of the separate strings, which you don’t need since each sequence is always two characters-so you save 64 bytes of memory. (Important if you want this chess game to run on a potato).
@toddeburch
@toddeburch 13 күн бұрын
Correction-I guess you would save a critical 63 bytes, not 64 :)
@LG-qz8om
@LG-qz8om 13 күн бұрын
So many ways this could be done. How about an array of 8 chars with each bit representing a pos on the board. And then 4 more char for all your pieces. In 12 bytes i have everything you need to know except the mapping. Maybe start with 4 char and used the 8 char board for mapping. (or something along those lines). Mapping is now an array of 12 char whose value is the board pos. Your input is translated into Piece bit & Place Bit. Managed by the Move & Display function. That would make it TIGHT.
@nunnukanunnukalailailai1767
@nunnukanunnukalailailai1767 12 күн бұрын
why not just a char[][2]
@toddeburch
@toddeburch 12 күн бұрын
@ because each array of two chars would get allocated in memory in a different place. This results in poor memory locality and worse performance because the CPU cache can’t stay hot. Plus setting up a 2D array is a pain.
@henrik3141
@henrik3141 Күн бұрын
Just found this channel. You have a really great and humble way of explaining things.
@dawiddulian2403
@dawiddulian2403 13 күн бұрын
That's interesting, I think you should continue this review.
@ladislavdobrovsky8826
@ladislavdobrovsky8826 6 күн бұрын
16:40 uint64_t is part of the standard, however optional (provided if and only if the implementation directly supports the type), defined in ; size_t is mandatory part of the standard used in standard library everywhere, e.g. size_t std::vector::size()
@l.t.c8.1.46
@l.t.c8.1.46 7 күн бұрын
If you store each piece as unique byte (ie black pawn = 2, white king = 55, etc) you would only need 64 bytes to hold all the spaces on the board which is only 8 uint64s - his solution needed 12 - one per piece - * 2 on each side = 24 uint64s.
@TranscendentBen
@TranscendentBen 13 күн бұрын
12:27 That first (and likely first SEVERAL) move should come back INSTANTLY. That's a standard opening move and there's a standard series of responses to it. These can be found by googling chess openings. Only when one side or the other makes a move that goes out of a standard opening should there be any time spend "thinking."
@salockin9515
@salockin9515 13 күн бұрын
I wrote the code. There is no opening book. The engine searched ahead 8 moves to make its first move. I don't know if I want to use an opening book or not because I want the engine to figure out each move. Maybe I will make the engine create an opening book but I don't think I want to use somebody else's chess games, I want 100% of the moves to be from the engine. I might change my mind in the future but for now, I don't want to add an opening book.
@mrglick5050
@mrglick5050 12 күн бұрын
@@salockin9515 Creating your own opening book honestly sounds like a fun idea. You could try to search a ton of moves ahead because it's gonna be baked into the engine anyways. Good luck either way!
@adams3616
@adams3616 9 күн бұрын
@@salockin9515I think that having some sort of opening book would be a good idea (coming from someone who knows nothing about coding and a bit about chess).
@dkotarvera11
@dkotarvera11 13 күн бұрын
With all the Chess engines Cherno reviews, I'd be interested to see how he would write his own chess engine
@seheyt
@seheyt 9 күн бұрын
25:47 "It's actually going to evaluate this function at runtime" - It's probably going to inline and potentially fold into a single constant depending on the way it's used.
@DeGuerre
@DeGuerre 13 күн бұрын
16:00 What do I think? I think you should put the constants in a namespace inside the header file, and put the "using namespace" inside that. That gives you the brevity that you want, and the "using" doesn't leak.
@toby9999
@toby9999 13 күн бұрын
No
@DeGuerre
@DeGuerre 13 күн бұрын
@@toby9999 Also a valid opinion. The central problem is that the "using namespace" as written leaks into any file that the header is included in. There are multiple solutions to that problem, mine is but one.
@Firestar-rm8df
@Firestar-rm8df 12 күн бұрын
@@DeGuerre It still leaks if this header depends on that one.
@drawmaster77
@drawmaster77 13 күн бұрын
Recently stumbled on this channel, and love it. Learning so much and I thought I knew C++ lol. We have a huge C++ code base at work. Nobody follows any standards whatsoever
@AlexandreJasmin
@AlexandreJasmin 13 күн бұрын
Regarding the character lookup table, in C99, an array initializer can use designators to put values at specified indices. AFAIK, it was never brought into the C++ standard but constexpr gives more flexibility when initializing static data anyways.
@BenjaminWheeler0510
@BenjaminWheeler0510 13 күн бұрын
Gcc probably supports it
@vast634
@vast634 12 күн бұрын
Chess engines usually come with a database for openings that cover the first few moves deemed optimal. But calculating them works too of course. More interesting in the code is what he used for optimizations to prune the tree of possible moves, and how he evaluates the final positions in the tree.
@RandomGeometryDashStuff
@RandomGeometryDashStuff 13 күн бұрын
24:37 why not use std::array (biggest number in array is 11 which is small enough to fit in 8 bits)?
@salockin9515
@salockin9515 13 күн бұрын
I wrote the code. The reason I did this is because I eventually use the value I get from that array to index memory. I want to avoid an implicit cast from std::uint8_t to std::size_t
@EmilyGamerGirl
@EmilyGamerGirl 3 күн бұрын
For something like string view literals, I would absolutely allow that in a header- though, for standardization, I would probably put it in a header that's included everywhere, simply putting that literal in scope for *the project*, as a consistency thing- but only if you plan to use it enough that it makes sense to do such. It feels acceptable for a project of this scope for certain. While I never would support general usings (`using namespace std;`) in a header, having some specific usings *consistently across the project* can be worthwhile- personally I would even do so for things like `std::optional` / `std::shared_ptr`, where they are in widespread use in the codebase.
@KevinInPhoenix
@KevinInPhoenix 13 күн бұрын
You spent all the time on the storage and never actually got to the code.
@catsandwich1259
@catsandwich1259 12 күн бұрын
Reason I had to dislike. I feel like I just watched 27 minutes of nothing.
@SyntaxDaemon
@SyntaxDaemon 13 күн бұрын
This has been interesting, would definitely be interested in more.
@subinaypanda9936
@subinaypanda9936 12 күн бұрын
That markup to markdown, now I also get that sudden realisation. How could I never thought of that 🤔
@LG-qz8om
@LG-qz8om 13 күн бұрын
When i learned Coding I learned from a guy who programmed Assembler for Boeing AutoPilots and did some stuff on Apollo. Everything had to be TIGHT and USE MIN SIZE and definitely OPTIMIZED for speed. Its just how i learned to think. So i use a lot of integers wherever i can because they go thru the CPU in ONE CLOCK CYCLE. But these days where RAM and Storage are cheap & plentiful none of that matters as much as it used to (unless your concern is Code Run Speed). One of my Educational tasks was to write a Function for EVERY process a computer could do (Every Interrupt, including mapping out video memory -- and Especially the BIOS). So i developed a practice of optimizing speed over anything.
@bidanfullko1
@bidanfullko1 6 күн бұрын
Scale matters... 3 pages in a browser cost 5 GB... Are you kidding me? Will always matter.
@LG-qz8om
@LG-qz8om 6 күн бұрын
You do understand we're discussing someone Learning Programming NOT a computer master. Learning, just get the job done (it works) Expert, do it perfect & efficiently. I think that's understood by all readers.
@khatdubell
@khatdubell 13 күн бұрын
RE: using std::uint64_t vs uint64_t My two cents. If you're including stdint.h, the correct way would be to use it without std, if you're using cstdint, you should use std. And if you're writing C++ post 2011, you should be using cstdint
@destiny_02
@destiny_02 12 күн бұрын
std:: before primitive types is unnecessary clutter. even with cstdint, the standard guarantees the types to be available in global namespace.
@khatdubell
@khatdubell 12 күн бұрын
​@@destiny_02 So confidently incorrect. On literally every account. First, they aren't "primitive types" aka fundamental types. 2nd the standard does NOT guarantee them to be in the global namespace. Just because compilers libraries put them in it, doesn't mean C++ standard does. Taken directly from the standard (any emphasis is mine): Example 1: The header assuredly provides its declarations and definitions within the namespace std. It *may* also provide these names within the global namespace. The header assuredly provides the same declarations and definitions within the global namespace, much as in ISO/IEC 9899. It may also provide these names within the namespace std. The standard doesn't forbid them from going into the global namespace, but it doesn't mandate that they are there. As for your opinion on "clutter", i take it you're the _using namespace std;_ type? Feel free to write your code however you want, but please don't try to misrepresent the standard based on implementation incidentals.
@destiny_02
@destiny_02 12 күн бұрын
@@khatdubell no im not the "using namespace std" type, but i am "using fs = std::filesystem" type. i believe overley verbose names hinders the readability of code. my bad on the standard part, but practically every implementation puts them in global namespace. also with c++23 modularized standard library, "import std.compat" guarantees them to be in global namespace.
@khatdubell
@khatdubell 12 күн бұрын
​@@destiny_02 Yes, i don't disagree. Overly verbose names can hinder readability,. This is actually why I don't use the string_literals. Generally, i use std::filesystem:: prefix every time i need it. However just 6ish months ago i was writing some code where there was an excessive amount of std::filesystem::path{something} all on one line to call a function. For that one section of code, at the smallest scope possible, i imported std::filesystem::path. IDK, maybe i'm a masochist? But back on topic, unless you import every name 1 by 1, a lot of your code is going to say `std::` already. After a certain point you don't even see it anymore. I personally don't see having it on fixed width types as cumbersome.
@adam3141
@adam3141 8 күн бұрын
In my opinion it is perfectly fine to import a type, ie. using std::filesystem::path using the previous commenter example. I use this almost all the time, except in header files where I will specify the full namespace. My job is software development and code readability is one of the most important things to consider because if I leave that particular project and someone takes over, they also need to understand the code and qualifying every single type with a namespace really does become noise to other people. If you structure your code well, importing multiple types with a using declaration makes your code a lot cleaner to read. People reading and reviewing your code knows that, take path example, path will refer to the class in std::filesystem and if for some reason you need use a different path object, then you can fully qualify that one.
@ast_rsk
@ast_rsk 13 күн бұрын
Would love to see a deeper dive on this project, very interesting and seems like it's loaded with nuance that can really help out that intermediate range of watchers.
@MatttKelly
@MatttKelly 9 күн бұрын
SE for almost 3 years here, I still struggle with camel case vs snake case. My current job prefers snake case but I prefer camel case.
@jmlopezponce
@jmlopezponce 7 күн бұрын
Hi, its true that you have 20 possible moves at the beginning but only if you look at the first depth of the tree. Once the tree start growing it gets computationally expensive really quick. It will be interesting to see if is using minmax with alpha/beta pruning or just a raw minmax. Also It will be nice to know how he define the value of a current state K, because there are some conventions as well (not only the value of the pieces itself). Great video, please continue
@mattewlefty991
@mattewlefty991 13 күн бұрын
The pitfall of programming in this modern era is obsessing over irrelevant details instead of solving the problem
@dino_source
@dino_source 8 күн бұрын
The author of the code should definitely use 1) consteval instead of constexpr for immediate functions 2) auto keyword (see AAA rule - almost always auto) 3) uniform initialization (curly braces initialization)
@gregthemadmonk
@gregthemadmonk 13 күн бұрын
26:40 - I personally would initialize a constexpr (or any global that requires non-trivial initialization) variable here with an immediately-invoked lambda - this way I can do non-trivial initialization but not create a separate callable that I'd have to then hide
@FlorianSimon-ob9gf
@FlorianSimon-ob9gf 13 күн бұрын
I'd say the memory representation of the state of the chessboard is probably pretty compact, but the overhead of doing bitwise operations to encode and decode your piece positions to perform logic on them might actually be slower than being slightly less cautious about space, if that's something you do a lot. I don't know how moves are calculated and stored, it could be that there are lots of optimizations to operate on chess pieces without constantly encoding and decoding positions to and from 64 bits integers, but I wouldn't be surprised if a less spacially conservative approach turned out to be faster to run. Optimizing for space alone might not be the right call here. If the author is certain it is, I'd say documenting why with a comment would be very interesting for readers. I can't infer much from the fact that positions are compact in memory. In fact, that raises alarms because, on the surface, it seems we've optimized something that didn't have any issue to begin with (a lot of naive approaches I can think of aren't that big in memory!) When talking about optimization, I'd much rather see how you take advantage of parallelism... And I wouldn't be very surprised if you actually needed multiple representations to hold the state of the chessboard depending on the situation because it's necessary to make certain optimizations work.
@kyoai
@kyoai 13 күн бұрын
For the char_to_piece array,I'd just use a struct containing both the letter and the number: struct PieceChar { char letter; size_t number; } and just have a std::array. You can then use either the letter or the number in a loop to find the other. With an array that small its probably faster than a map. Also, its much smaller than a array of 128 size.
@LG-qz8om
@LG-qz8om 13 күн бұрын
One last comment for everyone (especially newbies). The Primary Goal of all programming is to Solve the Problems that make the program work. If after you have done that, if speed is important you can learn what slows it down and do that better. What Works, in this day an age any solution which solves the problem adequately is good enough. If you can compute how to keep the robot from falling over in the time you have before it falls over then thats good enough. Today one can even be sloppy and still have a robot fast enough to balance. In my day, writing code for Boeing Aircraft we didn't have the luxury of being sloppy. I learned Programming in a time when RAM & storage were small & expensive. So EVERYTHING had to be written small and because processors were slower we had to optimize for speed too. So in the robot example if is wasn't FAST the robot fell. But ultimately Solving the Problem comes first. Make it better later. (Ideally you did it better the 1st time). Always improve your skills. Learn new tricks. Never stop learning. Get the idea? 1) solve the problem successfully. 2) make it better -- so you can do a lot more things in the same time. Getting to (2) is what makes your robot stand out from the crowd. (1) means you're a Good Programmer (2) makes you one of the Best in your Field.
@whukriede
@whukriede 11 күн бұрын
Yes, amen.
@darkagehibernia4843
@darkagehibernia4843 11 күн бұрын
I agree to certain point, but thats the reason why some many modern appliaction suck at performance. The Economist says why waste time on optimization if it works it works. The Result is MS Windows -- thats constantly disapointing for exampl because you alyways put performance etc into second positon. If you solve a problem why waste aditional time to optimize? I would argument part of the Problem is to be a s tight as possible on resosurces as well including security -----
@LG-qz8om
@LG-qz8om 11 күн бұрын
@@darkagehibernia4843 Windows itself slows things down. The 1st time i installed Windows on my computer ny impression was that it had slowed my conputer significantly. Programs that ran twice as fast in DOS now crawled with the overhead kist to make a GUI for non-computer users. The only reason you don't notice it now is that the computer itself is so much faster. Imagine what it would be withput the GUI overhead. New computer users will never know this -- except on slower things like cell phones.
@TanzinulIslam
@TanzinulIslam 8 күн бұрын
​@@darkagehibernia4843 Windows achieves its purpose of making you upgrade your computer every time 😅
@djthdinsessions
@djthdinsessions 2 күн бұрын
If this were an interview assignment, the moment I see "this is the best code ever", the moment I end the review ipso-fact with a big rejection 😂
@galacticminx
@galacticminx 3 күн бұрын
"Best" is highly subjective. What's best from one angle can be rather bad from another. Most things can only be best in one specific factor, because there are always compromises.
@andersama2215
@andersama2215 13 күн бұрын
I'm just going to point out. For all that time you spent on the array, there's no need to store the names of the squares, you can calculate them directly given the column or row or vice versa with a given name. Say we're calculating the index for "a8", you can just do math given the first and second character. Similarly given a string with at least two characters you can calculate the appropriate name using division and modulus operations. Now of course this opens you up to corrupting data by providing weird inputs, but, we're only dealing with 64 potential values.
@ScibbieGames
@ScibbieGames 13 күн бұрын
Dealing with malformed input is trivial here. Calculating would be much simpler. If not maybe faster?
@marcasrealaccount
@marcasrealaccount 13 күн бұрын
if (column >= 8 || row >= 8) { error... } Or if ((column & ~7) || (row & ~7)) { error... } char tileName[3] { 'a' + column, '0' + row, '\0' }; Super fast amirit :> Other way would just be column = tileName[0] - 'a'; row = tileName[1] - '0'; if (column >= 8 || row >= 8) { error... } Since column and row should just be uint8_t preferrably
@andersama2215
@andersama2215 13 күн бұрын
@@marcasrealaccount Don't forget, chess notation indexs from 1, not 0. My approach given the use of string_views and strings was: struct position { uint8_t file : 4; uint8_t rank : 4; }; constexpr position position_for(std::string_view name) { position pos{}; uint8_t err = (name.size() < 2) = 'a' && f = 'A' && f
@marcasrealaccount
@marcasrealaccount 13 күн бұрын
@andersama2215 Then use 0 based indexing internally and convert to/from 1 based when absolutely necessary means you get to use simple equations and simple error detection
@andersama2215
@andersama2215 13 күн бұрын
@@marcasrealaccount I was just commenting on the parts: '0' + row and row = tileName[1] - '0' which could easily be '1' + row row = tileName[1] - '1'. It doesn't particularly matter but presumably the input is normal chess notation.
@Bolpat
@Bolpat 13 күн бұрын
26:10 The create_char_to_piece could be "inlined" using an immediately invoked lambda.
@hesik3461
@hesik3461 13 күн бұрын
unreadable
@Bolpat
@Bolpat 12 күн бұрын
@hesik3461 Not more unreadable than a function definition.
@hesik3461
@hesik3461 12 күн бұрын
you are junior dev
@Bolpat
@Bolpat 11 күн бұрын
@@hesik3461 You have skill issues. At least I'm a dev and not an imposter.
@hesik3461
@hesik3461 11 күн бұрын
🤦
@parabalani
@parabalani 5 күн бұрын
Yes, continue reviewing it
@fitwithartin
@fitwithartin 12 күн бұрын
Please make an entire playlist on it!
@DjVortex-w
@DjVortex-w 13 күн бұрын
"Technically they are not part of the standard" What do you mean they are not part of the standard? They absolutely are part of the C++ standard. And why would you drop the prefixes? What for? The prefixes distinguish them from keywords and visually make it clear that they are coming from a standard library. In fact, the standard does not guarantee that the unprefixed names will be available if you include the version of libraries.
@sumikomei
@sumikomei 3 күн бұрын
I would still try to encapsulate the part of code using the namespace to some kind of scope that's then accessible externally, like maybe a struct or something. Or maybe put the code in that header file within its own namespace, so you then have a scope for the using stringview namespace.
@Astrixsmgaming
@Astrixsmgaming 13 күн бұрын
The notifications finally brought me here first😂 hi cherno hope the holidays went good for you
@FigeeR
@FigeeR 2 күн бұрын
Hi cherno i have a question, why initialize the position on the chess with the sv literal and not just pass an normal char?
@fullspecwarrior
@fullspecwarrior 12 күн бұрын
Loving the self-declared "Very good C++" on the repo :) Overall looks pretty good but I did notice: .h files including .hpp files reuse of std::array (I'd make this into a type, especially as it has a numeric literal in it). The entire engine looks very complicated to me but I understand that A) This is a port of the algorithm and B) I've never written my own chess game so it's entirely possible this complexity is necessary. It does make me want to write my own though to find out.
@Lichtstrahl92
@Lichtstrahl92 11 күн бұрын
For giving an advice like "don't think to much about your datatypes", there is a pretty extensive focus on datatypes in this video...
@minesadab
@minesadab 13 күн бұрын
"all done on the stack". The debugger is paused and we see the code push_backing an element into a vector 🙂 I am going to assume he hasn't created a custom stack-based allocator....
@salockin9515
@salockin9515 13 күн бұрын
I wrote the code. What I meant to say was I didn't use the new keyword. The only time there is stack allocation in the program is when the size isn't known at runtime. In those cases, I use a std::vector with vector.reserve()
@robby3467
@robby3467 13 күн бұрын
@@salockin9515 Brilliant work. I wouldn't let any of the petty criticisms worry you. I developed a chess engine 25 years ago based on the x88 board concept, and that was before the internet was much of a thing. I think I heard the "Chess Programming" channel mentioned. If so, yes, there's a heap of good stuff on his channel. And finally, your code looks way better than my engine code.
@nextlifeonearth
@nextlifeonearth 13 күн бұрын
The type aliases to uint32_t etc. are in the c++ standard and they are officially in namespace std. His code is therefore "correct", but I would also omit it in the cpp file. I may add it in a public header, to make it as correct as possible.
@destiny_02
@destiny_02 12 күн бұрын
but they are inherited from C library, and all C library stuff is in both std as well as global namespace. so not writing std:: before uint32_t is also correct
@adam3141
@adam3141 8 күн бұрын
@@destiny_02 This isn't true though. The standard doesn't mandate that the std namespace import the types from stdint.h even though most, if not all compiler vendors do this.
@devinegamingtv3427
@devinegamingtv3427 10 күн бұрын
His parents praised his tests with C+, so his C++ must be good
@la1m1e
@la1m1e 10 күн бұрын
There's no prize for perfection. Only and end tp pursuit
@RonyMarcolino
@RonyMarcolino 13 күн бұрын
Very interesting analysis; with each video serving as a unique C++ lesson. 😁
@Omnifarious0
@Omnifarious0 13 күн бұрын
10:00 - I kind of disagree. I mean, if you're talking about performance, you're absolutely correct. But it's a matter of signalling intent and readability. And for that, being careful about data types can be really helpful. 11:28 - This is actually a very compact representation. There are a maximum of 32 pieces. Each piece can be in one of 64 positions. That's192 total bits.That's way bigger than the 96 bits needed for the given representation. It takes advantage of the fact that there aren't 32 unique pieces. Even if you just had 4 bits (one of 12 different pieces) per square, that's 256 bits. Yeah, I don't know that there are any more compact ways to represent the state of a chess board. *Edit:* I was wrong. It's 768 bits, not 192 bits. So, not that compact. And there are at least 4 bits of state it would miss. Whether white or black was able to castle. Whether or not a white or black pawn could be captured by en-passant next move. Both could technically be inferred from move history. But for castling you'd have to go through the entire history to know. 22:30 - Actually, there, you want to use const strings precisely because of the small string optimization. It causes the size to be stored right next to the characters. There is no pointer, and no extra level of indirection. It will only work, of course, if your string is less than the small string optimization in size, if it is, it will be a lot faster and more compact than the string view will be.
@salockin9515
@salockin9515 13 күн бұрын
I wrote the code. I agree with you. I read on the internet that unsigned ints CAN be faster than signed ones, I don't know if they actually are or not but I figured I would use them anyway to squeeze out any bit of performance I can.
@ABaumstumpf
@ABaumstumpf 13 күн бұрын
@@salockin9515 signed can be faster in some scenarios - but it can also be a lot slower in others cause it has less UB. And any claims of Cherno about low-level performance like that? yeah absolutely unwarranted.
@jacksonlevine9236
@jacksonlevine9236 13 күн бұрын
​​@@salockin9515it doesn't work like that. Don't try to do that you'll just run into weird problems. Anyone here saying "unsigned is faster" or "signed is faster" is saying a non-starter non-idea, don't listen to them
@Omnifarious0
@Omnifarious0 12 күн бұрын
@@salockin9515 - I should do a review of your code. I have some criticisms of it that are very different than Cherno's, and it would be good practice to review it.
@salockin9515
@salockin9515 12 күн бұрын
@@Omnifarious0 I would appreciate it. My goal is always to become a better programmer, and specifically with this project I wanted to write perfect code.
@kevincozens6837
@kevincozens6837 13 күн бұрын
I wouldn't use an array containing the combination of two characters used for position references. It is very simple to check that first char is alpha and second is a digit and to do bounds checking. The time it takes to generate the two characters from a position or to parse a position string is negligible as that is a UI level thing. Even if it is showing you the moves it is thinking about making, the time to generate the two character positions is negligible compared to the think time.
@Haru02w
@Haru02w 12 күн бұрын
15:58 he just had to create an unnamed namespace and use all the "using namespace " he wants
@ashutoshsamantaray6596
@ashutoshsamantaray6596 13 күн бұрын
26:30 why not use consteval to enforce that rule? Also are you making a chess engine? You seem to have reviewed a lot of them, it would be really educational to see you build one and learn about the thought process! Also yes please review it!
@m4rt_
@m4rt_ 3 күн бұрын
If the code is OOP, it likely isn't the best it could be. The hierarchical structure of OOP makes sense to us, but it is far from performant, and can lead to code that is just a mess. The best solution is usually one that is specially crafted for the scenario, that is modeled around the data your are dealing with, rather than a one-size-fits-all generic solution, like OOP. Though, it seams like they are very exited about programming, which is a great start, and if they continue to learn and improve, they may very well create some of the best code ever written. Also, personally, I would handle the square names like this: typedef struct { // You could also store the string version if you need that a lot, so you don't have to calculate it every time, but this works. uint8_t row, column; } Board_Position; typedef struct { char column, row; } Position_String; bool position_string_to_board_position( Position_String position_string, Board_Position *board_position_result ) { // I would have had the board position as a return value if multiple returns were supported... if (board_position_result == NULL) return false; if (position_string.row < '1' || position_string.row > '8') return false; if (position_string.column < 'a' || position_string.column > 'f') // Maybe also handle capital letters... return false; board_position_result->row = position_string.row - '1'; board_position_result->row = position_string.column - 'a'; return true; } bool board_position_to_position_string( Board_Position board_position, Position_String *position_string_result ) { // I would have had the position string as a return value if multiple returns were supported... if (position_string_result == NULL) return false; if (board_position.row > 8 || board_position.column > 8) return false; position_string_result->row = '1' + board_position.row; position_string_result->column = 'a' + board_position.column; return true; } size_t board_position_to_index( Board_Position board_position ) { // I would have a separate boolean return value if multiple returns were supported... if (board_position.row > 8 || board_position.column > 8) return -1; const size_t columns = 8; return (board_position.row * columns) + board_position.column; } bool get_board_position_from_user( Board_Position *board_position_result ) { // I would have had the board position as a return value if multiple returns were supported... if (board_position_result == NULL) return false; // The length is 4 because we have 2 chars for the position, 1 newline, and 1 null byte. const size_t max_input = 4; // If the 3rd byte isn't a newline, something is wrong. const size_t expexted_newline_index = 2; char input[max_input]; input[expexted_newline_index] = 0; if (fgets(input, max_input, stdin) == NULL) return false; if (input[expexted_newline_index] != ' ') return false; Position_String position_string = *((Position_String *) input); return position_string_to_board_position(position_string, board_position_result); } int main( void ) { Board_Position board_position; while (get_board_position_from_user(&board_position)) { printf("Row: %d, Column: %d ", board_position.row, board_position.column); } }
@DannyTube69
@DannyTube69 11 күн бұрын
create_char_to_piece should just be a function with a switch case. It is easy read. The compiler optimises it and doesn't rely on magic char indexes.
@jumpjumpdiegaming
@jumpjumpdiegaming 12 күн бұрын
Hello from the guy who said hello at the airport 👋🏻 was great to meet you.
@ProfShibe
@ProfShibe 12 күн бұрын
Hello to the guy who said hello to the Cherno at the airport
@jumpjumpdiegaming
@jumpjumpdiegaming 11 күн бұрын
@ ya love to see it
@simonwillover4175
@simonwillover4175 12 күн бұрын
you don't need std:array, right? since size_t[10] is the same as array?
@DaemonJax
@DaemonJax 8 күн бұрын
Regarding that 128 element array named table that holds 12 real values using those 12 letters as the index... it's fine. I'd make it an array of chars though since you only need values 0 - 11. If this is just used for during user input, then performance doesn't even matter at all. But maybe it's not used just for user input? Dunno. If performance matters then you want that array as small as possible to help ensure it stays in cache, even if you need a more complicated algorithm to get the right index. Ideally, you wouldn't even need the array at all. Cache misses suck a lot on modern cpus and it's a problem lookup tables have, so i try to avoid lookup tables on modern cpus. But it looks like something used for user input, so whatever.
@cthutu
@cthutu 13 күн бұрын
You are wrong about uint64_t. You need the `std::` prefix unless you use C's standard header files (stdint.h). If you use `cstdint`, the prefix is required. Also, if you don't have either header files, `uint64_t` is unknown. Unless you typedef it (or use `using`), the `std` is required in a header. You're right about not using `using namespace` in a header as that can pollute your namespace in all your cpp files. Sigh... C++ header files. Why are modules not standard across the board yet!?
@matheusrocha5596
@matheusrocha5596 13 күн бұрын
I think he knows you need the 'std::' prefix, dude's a senior game engine programmer... I guess he just meant people normally don't use it that way, usually you'd employ one of the options you outlined.
@cthutu
@cthutu 13 күн бұрын
@@matheusrocha5596 I interpreted what he said as you didn't require the prefix and you can just use `uint64_t`, just like you can with `#pragma once#` (that is, it's a built-in). But even so, people do employ that way in headers (usually because they don't want to pollute cpp namespaces). However, mostly, people define their own types (like i32, u64 etc).
@undefinedchannel9916
@undefinedchannel9916 13 күн бұрын
For some reason it works in some versions of g++
@cthutu
@cthutu 13 күн бұрын
@@undefinedchannel9916 it doesn't on Microsoft's so it isn't, unfortunately, ubiquitous
@Hello_-_-_-_
@Hello_-_-_-_ 13 күн бұрын
Please continue on this project. I'm interested in how the set the memory size and if you could give us an example of using namespaces. Thank you
@jesusmgw
@jesusmgw 11 күн бұрын
This was the best code review ever performed for sure.
@Fr0sTyProductions
@Fr0sTyProductions 7 күн бұрын
Can you make a tutorial, or just reply to my comment regarding implementing EASTL? I’m trying to use EASTL as a Static Library, and in EASTL/allocator.h it defines its own new[] operators if you’re not creating a dll. It’s easy enough to create implementations for these new operators using malloc, but allocator then goes on to use the default delete[] operator which ends up giving me errors when objects are destroyed. Am I supposed to implement my own delete[] operator as well? It’s all just really confusing me.
@Starflight44
@Starflight44 10 күн бұрын
Personally I think that instead of just using twelve uint64_t values it would be cleaner (and use less stack space) to use structs like this enum Piece { NONE = 0b0000, WHITE_KING = 0b0001, WHITE_PAWN = 0b0010, WHITE_ROOK = 0b0011, WHITE_QUEEN = 0b0100, WHITE_BISHOP = 0b0101, WHITE_KNIGHT = 0b0110, BLACK_KING = 0b0111, BLACK_PAWN = 0b1000, BLACK_ROOK = 0b1001, BLACK_QUEEN = 0b1010, BLACK_BISHOP = 0b1011, BLACK_KNIGHT = 0b1100, }; struct Chessboard { enum Piece a1 : 4; enum Piece a2 : 4; enum Piece a3 : 4; enum Piece a4 : 4; enum Piece a5 : 4; enum Piece a6 : 4; enum Piece a7 : 4; enum Piece a8 : 4; enum Piece b1 : 4; enum Piece b2 : 4; enum Piece b3 : 4; enum Piece b4 : 4; enum Piece b5 : 4; enum Piece b6 : 4; enum Piece b7 : 4; enum Piece b8 : 4; enum Piece c1 : 4; enum Piece c2 : 4; enum Piece c3 : 4; enum Piece c4 : 4; enum Piece c5 : 4; enum Piece c6 : 4; enum Piece c7 : 4; enum Piece c8 : 4; enum Piece d1 : 4; enum Piece d2 : 4; enum Piece d3 : 4; enum Piece d4 : 4; enum Piece d5 : 4; enum Piece d6 : 4; enum Piece d7 : 4; enum Piece d8 : 4; enum Piece e1 : 4; enum Piece e2 : 4; enum Piece e3 : 4; enum Piece e4 : 4; enum Piece e5 : 4; enum Piece e6 : 4; enum Piece e7 : 4; enum Piece e8 : 4; enum Piece f1 : 4; enum Piece f2 : 4; enum Piece f3 : 4; enum Piece f4 : 4; enum Piece f5 : 4; enum Piece f6 : 4; enum Piece f7 : 4; enum Piece f8 : 4; enum Piece g1 : 4; enum Piece g2 : 4; enum Piece g3 : 4; enum Piece g4 : 4; enum Piece g5 : 4; enum Piece g6 : 4; enum Piece g7 : 4; enum Piece g8 : 4; enum Piece h1 : 4; enum Piece h2 : 4; enum Piece h3 : 4; enum Piece h4 : 4; enum Piece h5 : 4; enum Piece h6 : 4; enum Piece h7 : 4; enum Piece h8 : 4; };
@372leonard
@372leonard 13 күн бұрын
would you be willing to make a code review that focuses more on the algorithms/techniques and data_structures being used? the more high level stuff. instead of stuff like variable types, and variable name casing i think that would make for a very intersting code review
@galacticminx
@galacticminx 3 күн бұрын
I second this. It'd be good to hear more about the high level design and not so much nit picking over the details.
@Bolpat
@Bolpat 13 күн бұрын
16:35 Exactly, they’re not part of the standard, and even worse, uintN_t isn’t even guaranteed to exist. There’s zero downside to using the correct ones: std::size_t and std::uint_leastN_t. Pragma once is different because it helps reducing name pollution and makes the Intellisense faster opposed to include guards. If you dislike std::size_t, you can always just run s/(?
@khatdubell
@khatdubell 13 күн бұрын
Actually they are part of the standard. Go google search cstdint, you will see a file that reexports the C definitions INTO the std namespace. The C++ standard incorporates parts of the C standard. As for them not being guaranteed to exist, that is obvious on its face. How an you guarantee a uint64_t exists on an 8-bit platform? Mandating they all exist is impossible for a language that tries to be portable.
@whoeverofhowevermany
@whoeverofhowevermany 13 күн бұрын
4:44 Bill Ding! I haven't seen you since I delivered pizzas on the island
@mikefochtman7164
@mikefochtman7164 13 күн бұрын
Not so much a coding style issue, but looking at that char-to-piece array, it seems the default for 128 elements is zero, so an invalid input would return the same as 'P' ??? I think it's always a good idea to either test for valid inputs, or be sure that an invalid input doesn't silently return a 'good value'. Just one person's opinion.
@salockin9515
@salockin9515 13 күн бұрын
I wrote the code. You are correct. In a later commit to the one he cloned, I switched the array to use the Piece enum instead of numbers. Based on your comment I'm going to initialize the default elements to Piece::NO_PIECE. Thanks for the suggestion.
@dmk_5736
@dmk_5736 13 күн бұрын
25:30 the problem there is not 128 (which is too much), but using 8 bytes long size_t, while it could use uint8_t, and obviously to save even more memory really needed constexpr size_t size = 'z' - 'A' + 1; // 58 bytes and i assure you this solution would consume less memory than map, and would be faster. obviously before using such table you do need to subtract 'A' from your char to get valid table index, i.e. access function is needed. both table generation and table itself should be in internal namespace, only access function should be public
@loganb2198
@loganb2198 8 күн бұрын
Do you do code review for other languages or just C++?
@Zach-ul5fm
@Zach-ul5fm 12 күн бұрын
I think using "literals" namespaces in headers is fine. One reason to put literals in a namespace specifically called "literals" is to be able to use a "literals" namespace in headers with minimal pollution.
@tildessmoo
@tildessmoo 11 күн бұрын
Definitely behind "don't put 'using namespace x' in a header" and putting the header itself in a namespace. _Unless_ you have a header for whatever file has main() (or WinMain() or whatever), in which case the header should _not_ have its own namespace and its okay to use whatever "using namespace" lines you would use in your .cpp file, but I'd still recommend saving it for the main file if you can. (Although I'm also generally okay with giving "using namespace std" a pass. Most things in the std namespace are so well-known and unlikely to be replaced by your own implementation in most cases that collisions are extremely unlikely, and the few exceptions to that tend to be in nested namespaces anyway. Still bad practice if you're going for "perfect C++," but not the worst coding practice in the world either.) The thing that really gets me - and maybe it's because I haven't actually looked at the code myself, so maybe there's a reason the implementation used actually is better - is that constexpr array table. I get what you're saying, that using a constexpr table mapping char to int is better than anything else they could have used for that mapping - especially std::map - and that they did the right thing using the function variable to make sure it gets evaluated at compile time, but at a glance it looks like it's just for assigning a single letter representing each piece to a number. There's an even easier way to do that, and maybe it's the C in me versus this person's need to create textbook-perfect C++, but I look at that table and wonder why it's not just an enum.
@ivn414
@ivn414 13 күн бұрын
Using namespace in header? Believe it or not, straight to jail, right away.
@aljnistari
@aljnistari 11 күн бұрын
Skip to 6:17 if you actually want to see the code review
@RandomGeometryDashStuff
@RandomGeometryDashStuff 13 күн бұрын
18:54 why not array of uint16_t? all strings are 2 bytes
@1rez378
@1rez378 13 күн бұрын
I doubt those are used for any heavy lifting, and they are for UI instead. The technical debt would be bigger than any gain you could possibly get.
@daxeckenberg
@daxeckenberg 13 күн бұрын
I guess I'm not the weird one in that I start with the README as a way to guide what I need to do to make a repo useful and understandable. Kinda like a rubber duck code review.
@n00bc0de7
@n00bc0de7 13 күн бұрын
This is truly the code of the gods
@Sebanisu
@Sebanisu 13 күн бұрын
I don't think he needs the sv literal when he is defining the std::array so it's going to always be a string_view even with out the sv literal.
@salockin9515
@salockin9515 13 күн бұрын
I wrote the code. I think you are correct. However I like to be explicit in my code
@MyriadColorsCM
@MyriadColorsCM 13 күн бұрын
Yes, sometimes doing a 'using namespace' is justified if the part you are committing is long like "std::literals::string_view_literals".
@-Kailinn-
@-Kailinn- 13 күн бұрын
Yeaaah bring on more Cherno. Let's dive deep.
@GTLugo
@GTLugo 13 күн бұрын
I'm a little confused on the part where you say that the fixed-width integer types aren't part of the C++ standard. Aren't they included in the C headers (cstdint)? I'm very rusty with C++, so maybe I'm not understanding some nuance there.
@simonmaracine4721
@simonmaracine4721 13 күн бұрын
No, Cherno is actually wrong here. Every C symbol from the C's standard library is also defined in namespace std in C++. Best practice is to prefix every symbol from C with std::, as it improves consistency. It is not required though, as Cherno pointed out.
@GTLugo
@GTLugo 13 күн бұрын
@simonmaracine4721 Well the reason it's "not required" is because of "cstdint" vs "stdint.h". "cstdint" includes "stdint.h" which indeed allows you to use the types without any prefixing, but it also redefines them in the std namespace for extra safety with regards to which type you are referring to.
@khatdubell
@khatdubell 13 күн бұрын
@simonmaracine4721 Thank you.
@khatdubell
@khatdubell 13 күн бұрын
The C++ standard incorporates parts of the C standard. They _ARE_ part of the C++ standard. Unambiguously and definitively.
@TheFlyingMonkey200
@TheFlyingMonkey200 12 күн бұрын
yes keep reviewing very educational.
@KaiHenningsen
@KaiHenningsen 12 күн бұрын
You probably knew this, but Visual Studio isn't the only software to use .sln files. I'm currently doing a bit of C# with VSCode under Linux, and guess what? .sln files are in use. *And* it's portable.
The MOST IMPORTANT Considerations in Programming! // Code Review
19:11
ChatGPT vs Stockfish: ABSURD CHESS
25:01
GothamChess
Рет қаралды 979 М.
How to treat Acne💉
00:31
ISSEI / いっせい
Рет қаралды 108 МЛН
Cheerleader Transformation That Left Everyone Speechless! #shorts
00:27
Fabiosa Best Lifehacks
Рет қаралды 16 МЛН
Правильный подход к детям
00:18
Beatrise
Рет қаралды 11 МЛН
Is C BETTER than C++ for beginners? // Code Review
31:16
The Cherno
Рет қаралды 94 М.
Антон Полухин - Грязные C++ трюки из userver и Boost
1:00:00
C++ Russia — Конференция по разработке на Cpp
Рет қаралды 9 М.
Stop using std::vector wrong
23:14
The Cherno
Рет қаралды 170 М.
Reacting to Controversial Opinions of Software Engineers
9:18
Fireship
Рет қаралды 2,2 МЛН
the new rsync exploit is sort of hilarious.
11:02
Low Level
Рет қаралды 198 М.
Why Majora's Mask's Blue Dog Took 25 Years to Win the Race
21:04
Vidya James
Рет қаралды 3 МЛН
Hacking This Terrible DRM
15:20
Nathan Baggs
Рет қаралды 111 М.
Should you learn C++?? | Prime Reacts
20:29
ThePrimeTime
Рет қаралды 423 М.
A New Era for C and C++? Goodbye, Rust?
9:08
Travis Media
Рет қаралды 137 М.
how Google writes gorgeous C++
7:40
Low Level
Рет қаралды 995 М.
How to treat Acne💉
00:31
ISSEI / いっせい
Рет қаралды 108 МЛН