Code Review: CPP

แชร์
ฝัง
  • เผยแพร่เมื่อ 21 พ.ย. 2024

ความคิดเห็น • 154

  • @kirsanov2008
    @kirsanov2008 หลายเดือนก่อน +9

    it's funny to see how json engineers trying to make jokes out of c++

    • @annorome
      @annorome หลายเดือนก่อน

      lol

  • @rodrigolj
    @rodrigolj ปีที่แล้ว +112

    I don't feel that a cpp project is ready when there are no memory leaks to be found. I hope they fix it on v1.1

  • @theinsane102
    @theinsane102 ปีที่แล้ว +198

    imo cpp code is more readable than rust

    • @jgndev
      @jgndev ปีที่แล้ว +13

      it’s true

    • @TheVimeagen
      @TheVimeagen  ปีที่แล้ว +62

      fully agree

    • @ac130kz
      @ac130kz ปีที่แล้ว +19

      c++98 maybe, not the latest c++20/23 stuff

    • @froloket
      @froloket ปีที่แล้ว +26

      3:28 is that readable?!

    • @Artentus
      @Artentus ปีที่แล้ว +24

      Depends. If you write C++ like it was C then yes, it's more readable.
      But if you use all the modern stuff to make it behave closer to Rust it becomes much uglier.

  • @ЕгорКолов-ч5с
    @ЕгорКолов-ч5с ปีที่แล้ว +16

    Lmao, this [[likely]] reminded me of this:
    "INTERCAL has many other features designed to make it even more aesthetically unpleasing to the programmer: it uses statements such as "READ OUT", "IGNORE", "FORGET", and modifiers such as "PLEASE". This last keyword provides two reasons for the program's rejection by the compiler: if "PLEASE" does not appear often enough, the program is considered insufficiently polite, and the error message says this; if it appears too often, the program could be rejected as excessively polite. Although this feature existed in the original INTERCAL compiler, it was undocumented"

  • @CheaterCodes
    @CheaterCodes ปีที่แล้ว +30

    The [[likely]] is a hint to the compiler to let it make assumptions it usually can't. It can then make the likely path branch-free, or emit hint instructions for the cpu (or similar). This can be useful in certain scenarios if the cpu branch prediction fails systematically (probably not here).
    Note that rust has something similar with the #[cold] attribute

    • @JackTheDev
      @JackTheDev ปีที่แล้ว

      oh, CheaterCodes.
      When you say "similar" does that include having different speeds? when it gets to the instructions, do they differ in any meaningful way? Does LLVM vs GCC have an effect on this (for C++ as Rust is only LLVM AFAIK)?

  • @whoopsimsorry2546
    @whoopsimsorry2546 ปีที่แล้ว +57

    [[likely]] does not help branch prediction, in fact there's nothing you can do to force branch prediction. [[likely]] optimizes branches, inlines where possible to make code run faster. Most of the compilers have an internal % system which tries to predict which branch is more likely your code to take, and based on that % it optimizes it by inlining, [[likely]] is a way for the programmer to raise that % for a certain branch. Nothing to do with branch prediction - common misconception.
    To be able to use [[likely]] without pessimizing instead of optimizing you need deep understanding of how your complier optimizes the code in the first place, to know where it uses lookup tables. Usually you shouldn't use that C++ feature unless you've studied the assembly your compiler generates and the performance you're getting out of it and are willing to spend the time on even the last nanosecond.

    • @horriblyterrible1121
      @horriblyterrible1121 ปีที่แล้ว +11

      +1 This is to be used only when there is heavy operation on one branch, but is not really likely to happen. Like, say, you want to push some big strings into a set, otherwise return, and you know that the existence of a string in the set is more likely. This is where this attribute might help, and lead to lesser code generation. This will not, as correctly mentioned, predict branches. The compiler might still fully ignore it. To include this attribute in such "lightweight" branches is really unnecessary.

    • @TheVimeagen
      @TheVimeagen  ปีที่แล้ว +6

      weird.... yeah, i have not much idea about some of c++'s things

    • @SimonBuchanNz
      @SimonBuchanNz ปีที่แล้ว +1

      ​@@TheVimeagen it's really just standardizing a long long history of implementation defined attributes. You don't need to care about it pretty much ever, it's a bit extra here.

    • @TsvetanDimitrov1976
      @TsvetanDimitrov1976 ปีที่แล้ว

      That's not entirely true in the general case. There are architectures where a hint can be generated for the processor(for example the spus on PS3)

    • @whoopsimsorry2546
      @whoopsimsorry2546 ปีที่แล้ว

      @@TsvetanDimitrov1976 Благодаря за уточнението! :)

  • @vaisakh_km
    @vaisakh_km ปีที่แล้ว +49

    Tom might [[likely]] be the editor for CppCoreGuidelines 😆

  • @manwithmannynames
    @manwithmannynames ปีที่แล้ว +8

    7:20 AFAIK the way the compiler usually uses the "likely" and "unlikely" builtins is that they will place the "unlikely" branch code away from the main program flow, so the main execution path fits in less cache lines.

  • @charactername263
    @charactername263 ปีที่แล้ว +7

    [[likely]] has nothing to do with the brand prediction. It's a locality optimization that means the [[likely]] branch will be close to the code preceding and succeeding the branch, with the [[unlikely]] branch further away. The only time there needs to be a potentially far jump that might cause cache misses would then only be in the [[unlikely]] path. It's for e.g critical path optimization where you might want a path that is not necessarily "hot" in that it might not run frequently, but it should run *as fast as possible* regardless. An example might be a trading system where most of the time the potential trades are rejected by a branch, but if in the minority of trades the trade is not automatically rejected you want the execution to be the fast branch.
    You can manipulate the branch predictor by spoofing/warming the branch but you can't cache optimize branches without the [[likely]]/[[unlikely]] language feature. It's very cool 😎

  • @StuartLoria
    @StuartLoria ปีที่แล้ว +1

    I captured an image from the code here to create the dirty code poster, unreadable, hard to maintain, a nightmare to inherit.
    The ego of expressing your logic in terms of your implementation details rather than using the requirements language, robing the program of the opportunity to document the intension of the product in the code itself (while it was clear and fresh in the author's mind), assuming there will be no bugs, no changes in the requirements hence no need to open the blackbox and no changes in team roster, I love it.

  • @CallousCoder
    @CallousCoder ปีที่แล้ว +5

    Ive never moved passed C++17 and I saw some very new things. I liked the likely though. But let’s be honest, it doesn’t make the code more readable. But it does optimize away a likely branch something we did in demo coding in assembly on the C64 all the time.

  • @andylyounger74
    @andylyounger74 ปีที่แล้ว +5

    [[likely]] So its maybe easier to understand if you flip it on its head and look at [[unlikely]] instead. In that case you are telling the compiler that this code path is super unusual and will let it make better inlining / conditional choices. For example an assert() implementation by definition is unlikely to fire and the assert handling code (for when it fires) could benefit from being moved out of line thus improving the general performance as less instructions and branching can be run in the non-asserting case.

    • @andylyounger74
      @andylyounger74 ปีที่แล้ว

      for a [[likely]] example, think of std::vector push_back. In most cases it won't need to reallocate memory (especially if you are a good citizen and remember to reserve up-front), so could potentially benefit from the hint when it checks if it has enough capacity before the physical object copy. In this case it could potentially move the else and resize for when that fails out of line (by definition they would now be 'unlikely'), and thus get better performance (less instructions run in the common case) and benefit from better comdat folding (smaller code due to de-duplication - a common linker trick where it removes duplicated code which can also helps icache (instruction cache) efficiency --- less code == generally more potential cache hits). Think how big code could get if every 'push_back' has the explicit resize code duplicated in it,

  • @SimonBuchanNz
    @SimonBuchanNz ปีที่แล้ว +15

    A few things to note here, as a recovering C++ user:
    * For some reason, compilers start implementing standards way ahead of the year. They're adding C++27 features right now 😮
    * I think private first, trailing _ for members is Google's house style? It's overall pretty nice, but the point of the underscore is so you can directly reference them without the "this->" unambiguously, so it's lame those are still there...
    * Standard library source is run through uglifiers so every identifier uses the reserved "_Uppercase", and every reference is fully qualified, to defend against macros breaking things. I don't think they actually edit the source like that!
    * noexcept is a replacement for except(), which is now completely deprecated. The difference, IIRC is that it's part of the signature so you can specialize a template if you know the generic function definitely won't throw, eg avoid putting expensive rollback handling. If/when Rust gets specialization this would be like specializing on error type !. Here it's not doing much other than checking the body can't throw, eg that every method it calls is also noexcept.

    • @widnyj5561
      @widnyj5561 ปีที่แล้ว +2

      additional fun fact - move operators have to be noexcept, too (but I guess it depends on compiler flags, as exception during move can brake source object without, effectively losing data) - which, knowing cpp, can be just "we don't give a fuck; UB, but gib sped"

    • @simonfarre4907
      @simonfarre4907 ปีที่แล้ว +1

      @@widnyj5561 as far as I am aware move operators definitely don't have to be noexcept.
      However move operations for obvious reasons, like the one you stated, should be implemented in ways that it doesn't throw. And seeing as how move operations technically don't do allocations (necessarily, they can, but for brevity's sake, lets say they don't) one can be pretty certain it's a non throwing operation.
      What I find unfortunate is that all my private code for hobby projects gets absolutely littered with noexcept everywhere. It should be the default.

    • @SimonBuchanNz
      @SimonBuchanNz ปีที่แล้ว

      @@simonfarre4907 you actually don't want it as a default in general, for the same reason you don't want Copy by default in Rust: it's a breaking change to remove it, while it's fine to add. If you later find out that you do want to throw (or rather, use other APIs that can throw) then you're stuffed.

    • @simonfarre4907
      @simonfarre4907 ปีที่แล้ว

      @@SimonBuchanNz yeah I totally get why it's not default now, obviously. But with the privilege of hindsight, it should have been.

    • @SimonBuchanNz
      @SimonBuchanNz ปีที่แล้ว

      @@simonfarre4907 no, I mean backwards compatibility problems for your changes, not if they added it now. Imagine your public function happens to not throw exceptions, you left it at the default, then you change it to throw later. Obviously just throwing when you didn't throw before is a compat hazard, but in C++ the default assumption is anything can throw, so currently this is ok. But with nothrow, you can actually explicitly depend on the function being nothrow, most obviously by calling it from another nothrow function. Just removing the nothrow qualifier is a hard breaking change!
      For this reason, you should only add the qualifier when you're making it part of the API guarantee, not just because you happen to but currently throw anything.
      Making it the default is then a problem for two reasons: you're much more likely to accidentally expose a public API as being nothrow, and you're much more likely to accidentally depend on it being nothrow by calling from a nothrow function.

  • @themohmand
    @themohmand 9 หลายเดือนก่อน +1

    I was taught the "private first, public afterwards" approach, so that part of the code seemed normal to me

  • @__kvik
    @__kvik ปีที่แล้ว +1

    5:27 Yes, function return type on its own line is useful for grepping function names without clever tooling; but also this is C++, where you often have like a function template returning a templated type so splitting all that to even more lines is just a reasonable thing you do and doing it for simple types as well is then just for consistency.

    • @00wheelie00
      @00wheelie00 8 หลายเดือนก่อน +1

      But he's using c++ 23, he can use trailing return types. It makes no sense to do that anymore.

  • @ernesto906
    @ernesto906 ปีที่แล้ว +7

    so this is sort of non standard formatting for C++

  • @MrAbrazildo
    @MrAbrazildo ปีที่แล้ว +1

    0:30, that's because it's indeed the best so far. aka Rust+.
    2:00, private is default for class, as public for struct. This private line was optional.
    2:10, it's a convention, for when you want to write getter/setter with the same name. Since those f() calls will be much more often seen than the class inner data, these ones are those who change their names, by adding '_'. Not before, due to macro convention.
    2:20, this convention was created by a hungarian programmer, who used to add a letter for the type of the variable.
    2:47, it's entirely optional. I use to write struct, to get public as default (1st, as you say). Because if I want to use a typedef along the class definition, I need to declare it before. And since I want it to be used outside the class too, it needs to be public, to not has to break encapsulation - btw, C++ has the best from any language.
    3:08, an union with tags. It's meant for when you want more than 1 variable beginning at the same address in memory. This saves memory, at the cost of only 1 may be used at a time.
    3:29, it has all those scopes (::) because C++ has a philosophy of "only pay for what you use". It makes easier to write more light weight apps. So everything is subdivided into optional "sections". static_assert is for defensive code proposes, to raise compile errors if the user does something wrong.

  • @topticktom
    @topticktom ปีที่แล้ว +1

    I really tried to make sense out of those Template and Type creations, but even with all the JDSL jeniusness I could come up with a simple explanation of the code.

  • @allalphazerobeta8643
    @allalphazerobeta8643 ปีที่แล้ว +11

    I would avoid using [[likely]] unless you are very sure of your assumptions. Do profile-guided optimization (PGO) not assumption guided optimization . Either-way this could help a lot with automatic unrolling of loops properly. Of course, gathering and keeping real world data up to date is difficult as Itanium proved.

    • @TheVimeagen
      @TheVimeagen  ปีที่แล้ว +4

      yeah, i don't like the idea that i have to know what is the best course of action, i would rather have a compiler tell me :)

    • @VivekYadav-ds8oz
      @VivekYadav-ds8oz ปีที่แล้ว +1

      Well sometimes you know for eg: a certain condition will only hold true for the first k items in the loop. Let's say you don't want to loop over those items in a separate for-loop. I find this could be useful in those cases.

    • @allalphazerobeta8643
      @allalphazerobeta8643 ปีที่แล้ว +2

      I just realized people might not be familiar with PGO, or profile guided optimization. You compile a version of the program that produces profile data. On gcc you use '-fprofile-generate' then you run it with inputs or data representative of typical usage. (Or you could deploy it. ) The program will create '.gcda' files. Then you recompile it with -fprofile-use and either '-O2 ' or '-O3' and whatever else you need. The profile will help the Compiler figure out how to best do the optimization. Remember, the itanium was nearly completely reliant on profiled optimization, since it's was designed to avoid doing Branch Prediction and Speculative Execution. (Which I believe was the word Primeagen was looking for)

    • @redf1sh
      @redf1sh 3 หลายเดือนก่อน

      PGO has some disadvantages, e.g. if you make bad train data, compiler can easily "optimize" your program and it can be slower even x10. If you make some changes in your code, you need to get profile data again. In contrast, hints will live and be reliable until some big refactoring

  • @MH_VOID
    @MH_VOID ปีที่แล้ว +3

    Rust has something similar to '[[likely]]', in core::intrinsics::{,un}likely. Way it works is it takes a bool and returns it, and adjusts the likely/unlikely path to be more/less likely to be branch predicted and CPU cached, I believe. You can use it like `use core::intrinsics::likely; for i in 0..15 { if likely(i % 5 != 5) {foo()} else {bar()} }` (obviously a super contrived example but you get the point)
    Where do I find the full spec for this thing? I might want to have a dab at it with Z Shell or perhaps elisp. My personal specialty is in writing long shell pipeline abominations in ZSH. If I could horrify others with it that'd be nice

  • @chikinrasshu
    @chikinrasshu ปีที่แล้ว +1

    because c++ types get stupidly long, you end up doing type function_name because std::map covers the whole line. (or auto)

    • @chikinrasshu
      @chikinrasshu ปีที่แล้ว

      and [[likely]] is a compiler intrinsic that allows it to optimize assuming the branch is true more often than false.

  • @Xe054
    @Xe054 ปีที่แล้ว +6

    Am I the only one who didn't understand a single thing that happened in this video?

  • @Je3f0o
    @Je3f0o ปีที่แล้ว +3

    variant is template meta programming in compile time type checking added in cpp 17.

  • @orychowaw
    @orychowaw ปีที่แล้ว +10

    At 6:26 why are there explicit this-> strewn all over the code? There's already the underscores appended to mark member variables. Even without that is highly irregular. Unlike the private first.

    • @user-ge2vc3rl1n
      @user-ge2vc3rl1n ปีที่แล้ว +2

      because the -> operator is the most hackerman operator there is

    • @isodoubIet
      @isodoubIet 5 หลายเดือนก่อน

      this-> is unnecessary here, but it does make sure the name is still accessible even if defined in a base class so maybe they were future-proofing for that? Idk I wouldn't write it that way either.

    • @TehKarmalizer
      @TehKarmalizer 5 หลายเดือนก่อน

      It is to differentiate members from non-members, not public and private. Not all members will have the private underscore suffix if there are any public. It may not strictly be necessary, but some of us prefer the explicitness.

    • @peternimmo74
      @peternimmo74 5 หลายเดือนก่อน +1

      I hate the use of this-> which is mostly unnecessary, as you say templates is the one place where it is sometimes needed.

    • @peternimmo74
      @peternimmo74 5 หลายเดือนก่อน

      Using this-> instead of having your parameter names different from the member names makes everything ugly.
      Headers are usually the only place where 'using namespace' is dreadful. Using std:: is preferred in headers, but part of the reason C++ often looks so ugly is the lack of adding 'using namespace' in .cpp files. In 28 years of programming I've never found it causing problems.
      You would never use the full names in C#, if you did the same as alot of C++ code does in C#, it too would look pretty ugly.

  • @mattmurphy7030
    @mattmurphy7030 ปีที่แล้ว +8

    Who wrote this? Returning from void at the end of a function? Do they know C++?

    • @daniels3617
      @daniels3617 ปีที่แล้ว +6

      There is a reason for that. If you eventually add a return type to the function, you'll get a compiler error. Without the empty return, you're only going to get a warning on default settings.

  • @mark_fi
    @mark_fi ปีที่แล้ว

    [[likely]] is just a weaker and standardized version of what has existed for a long time in C/C++ e.g. in the form of __builtin_expect(). This is IIRC what also Linux kernel also uses (the likely/unlikely macros typically expand to __builtin_expect() if supported by the compiler).

  • @asdfasdf9477
    @asdfasdf9477 ปีที่แล้ว +1

    That constructor 1 introduces implicit conversion from std::string 2 copies the string twice 3 const does nothing except confusing the reader 4 throw std::exception() is punishable by death 5 return does nothing at all . Noexcept makes it call terminate if exception is thrown, no stack trace. Optimising branch prediction in the code that is 10% complete is a bad sign. Requiring cpp23 and not using generator for lexer is strange, as is using both discriminator and std::variant in token. Also, std::string for multi byte token means heap allocation, use string_view or indexes for both single- and multibyte tokens, that will allow you to report line/column in error messages.-Wall, clang-format and asan are your friends.

  • @NoName-y2e6c
    @NoName-y2e6c ปีที่แล้ว +4

    im surprised both of you haven't seen private-first declarations in cpp; i had thought it was a common practice

    • @JuusoAlasuutari
      @JuusoAlasuutari ปีที่แล้ว +1

      The sad thing about that snippet was that ` private` at the beginning of a ` class` is redundant. You can just slap members in there, and everything before the first ` public` is implicit ` private` .

    • @NoName-y2e6c
      @NoName-y2e6c ปีที่แล้ว +4

      @@JuusoAlasuutari sure, classes are private by default but I like to be explicit about intentions

    • @JuusoAlasuutari
      @JuusoAlasuutari ปีที่แล้ว

      @@NoName-y2e6c that's reasonable, I can see the upside in that. Also it makes it possible to change between class and struct with no reordering of members. Although that sort of thing isn't very common.

    • @sournois90
      @sournois90 6 หลายเดือนก่อน

      ​@@JuusoAlasuutarido you mind explaining briefly to me when to use a class and when to use a struct?

    • @isodoubIet
      @isodoubIet 5 หลายเดือนก่อน

      @@sournois90 Use a class when it has invariants to maintain. Use struct when it's a bag of members with no nontrivial behaviors.

  • @simonfarre4907
    @simonfarre4907 ปีที่แล้ว +1

    I always do the member variables that are private up top, first. Because these, _always_ turn out to be the most interesting and crucial things.
    Think of it as attempting to look like Rust, without actually being good, like Rust.

    • @vladimirkraus1438
      @vladimirkraus1438 ปีที่แล้ว +2

      So you are saying that you think implementation details are more important than public API? Really?

    • @simonfarre4907
      @simonfarre4907 ปีที่แล้ว

      @@vladimirkraus1438 For application development - absolutely. For library development; no.

    • @simonfarre4907
      @simonfarre4907 ปีที่แล้ว

      @@vladimirkraus1438 You can think of it like this; a public API is only ever important in library development. It needs to be stable, it needs to produce the same outputs, no matter it's internal details (which can change under the end-user's feet from version to version, but still produce the same output).
      This is where public API is of import. For application development, like say, a debugger like GDB or RR; why would the public API be the most important? They're not libraries. What's most important is their functionality, their performance. Any change to the underlying system _will_ be changes to the implementation details.
      This means, what data structures are being used, what is the layout, when are they read and written, so on and so forth. These are all implementation details. Rust was *brilliant* when they realized this and separated the declaration & definition of a type and it's implementation, or behavior.

    • @vladimirkraus1438
      @vladimirkraus1438 ปีที่แล้ว +2

      @@simonfarre4907 Why do you distinguish writing library or application? All is just a code. And if implementation details are the most important to you, then you are doing something wrong.
      Btw. how are you ordering the methods? Private ones first at the top too? Then protected ones and public ones at the end?

    • @simonfarre4907
      @simonfarre4907 ปีที่แล้ว +1

      @@vladimirkraus1438 False. Application development and library development differ *massively* in what requirements and constraints are placed on both the developer and end product.
      The ordering of methods is irrelevant, but after the definition of the actual data type, I proceed like usual, public first. There's plenty of applications that you use *right now* that do what I've said here.

  • @cristianinujazznight3044
    @cristianinujazznight3044 7 หลายเดือนก่อน +1

    Wow, Is like seen two old guys just talking about C99 :D
    Come on!!! You streamer guys should try to make a tetris in C++23, and will see THE POWER of: Spending a week to make a Cmake, Spend another week to try to add Conan/vcpkg, try to install SDL2/raylib. Then after a month, you will get beard, so you can now, Spend another week why cmake does not recognize SDL2/Raylib. And now, after two months, you are ready to start coding C++23. Thats how to do it :D

  • @MrAbrazildo
    @MrAbrazildo ปีที่แล้ว +1

    4:09, it's just a more protected collection of integers. Not as good as Rust enums. But I guess it's possible to emulate that with an array of variants...
    4:40, you can store anything in a std::map (it's a template class afterall). However, it's infamous, because it seems that it's implemented as a linked list, which is a fairly slow data struct. So often someone is seen implementing his own version of it (which I recommend, btw).
    4:51, did you just swallow a bank card?
    5:18, this prevents an annoying potential error from fast C initializations.
    5:24, it's really bad. I don't use, neither recommend. 5:37, they are deactivated for f()s marked as noexcept.
    6:57, it's a hint for the compiler, to optimize the code: it's likely to happen this than the other alternatives.
    And those 'this->' are unnecessary: by default the class variables are used; there's no ambiguity.
    7:40, with old style enums, I like to reduce this kind of code to 3-5 lines, by creating sorted arrays, searching the char in 1, via some algorithm, and using the resulting index on the other. It's as fast as elegant.
    8:20, this is just a reference for a class object that lives on the stack memory, meaning it's not allocated by the user. This token may be string or a char at a time. std::string makes automatic allocations, so it'll free its memory for you. The reference works as the borrow from Rust, I guess. What changes from it in this f() will remain after.

    • @isodoubIet
      @isodoubIet 5 หลายเดือนก่อน

      std::maps are not implemented as a linked list, they're a red-black tree (I suppose AVL might work as well, but red-black is the most common).
      exceptions are fantastic and very much recommended. In some cases mandatory (such as here).

  • @PhatPazzo
    @PhatPazzo ปีที่แล้ว +2

    Rust also has something like [[unlikely]] with the function attribute #[cold].

  • @pabloqp7929
    @pabloqp7929 ปีที่แล้ว +1

    most iconic SWE duo

  • @Arwahanoth
    @Arwahanoth 9 วันที่ผ่านมา

    [[likely]] and [[unlikely]] just order the code so that the "most" likely branch is the closest to the conditional jump. But it is not as good as it seems for modern CPUs (like < 15 years old lol)

  • @Messmerd97
    @Messmerd97 ปีที่แล้ว +3

    That lexer::read_char() method is really bad: A void argument, pointless usages of this, using += 1 instead of ++, a pointless return, etc. It's really weird.
    EDIT: It looks like the constructor also makes an unnecessary copy of the input string.

    • @TheVimeagen
      @TheVimeagen  ปีที่แล้ว +2

      make a pr?

    • @Spongman
      @Spongman ปีที่แล้ว

      @@TheVimeagen I made a PR.

  • @zoso25
    @zoso25 4 หลายเดือนก่อน

    Why do we nede this-> ? Just referring to the member variable doesn't work?

  • @AsbestosSoup
    @AsbestosSoup ปีที่แล้ว

    would be cool if [[ likely ]] was used to tell the compiler which branch is "more likely" (duh), so that it performs sort of a hotspot optimization like JITs do, analyzing the runtime. Just that in this case there is no analysis of course, but it assumes the programmer's directive is reflective of runtime behavior. I am really afraid JITs will get significantly better than AOT compilers, and that I'll be forced to migrate to Java 🤮.

  • @evanstachowiak9583
    @evanstachowiak9583 หลายเดือนก่อน

    private before public is in alphabetic order.

  • @cheebadigga4092
    @cheebadigga4092 ปีที่แล้ว

    bros, LLVM have their own APT repos

  • @kunaltiwari7970
    @kunaltiwari7970 4 หลายเดือนก่อน

    which plugin was that 6:33

  • @nevil2151
    @nevil2151 ปีที่แล้ว

    Would love to know the color scheme? 😅

  • @Sobioytccc
    @Sobioytccc 11 หลายเดือนก่อน +1

    The only reason why most programmers choose to define private member before public is to access private member variable in public function. Otherwise cpp compiler starts to puke 🤮 right back to you. It’s like I don’t recognise it, who is he/she ahhhhhhhhhhhhhhh😂

    • @TehKarmalizer
      @TehKarmalizer 5 หลายเดือนก่อน

      I’ve seen alternating private/public/private/public with members first, and then the methods.

    • @amadeusk525
      @amadeusk525 3 หลายเดือนก่อน

      ​@@TehKarmalizer I do that. It looks horrible but it helps my ADHD brain keep things organized lol

  • @Cromius771
    @Cromius771 4 หลายเดือนก่อน

    Variant on a string, char is dumb. String has an internal variant on its pointer for use with the small string optimization at least on most standard library implementations. So doing that yourself is likely useless

  • @abrarmasumabir3809
    @abrarmasumabir3809 ปีที่แล้ว

    someone know what is the color scheme?

  • @airman122469
    @airman122469 ปีที่แล้ว +1

    … the c++ standard library is a pain to look at. It’s worse than the code in the Boost libraries.

    • @mattmurphy7030
      @mattmurphy7030 ปีที่แล้ว +6

      It's not meant to be looked at, it's meant to be portable. The "pain to look at" is literally a carefully guarded feature.

  • @oredaze
    @oredaze ปีที่แล้ว

    Rust - -
    rofl xD

  • @distant6606
    @distant6606 ปีที่แล้ว

    trash dev catching strays again 😂

  • @annorome
    @annorome หลายเดือนก่อน

    C++ > Rust.

  • @exvimmer
    @exvimmer ปีที่แล้ว +3

    You don't have to nag about something that you don't understand. Just a waste of time.

  • @Spongman
    @Spongman ปีที่แล้ว +11

    terrible c++ code

    • @musdevfrog
      @musdevfrog ปีที่แล้ว

      like your mom wrote it.

    • @Spongman
      @Spongman ปีที่แล้ว +9

      @@musdevfrog no, my Mom's a significantly better c++ programmer than the monkey who wrote that, and she's never coded c++.

    • @jarvenpaajani8105
      @jarvenpaajani8105 ปีที่แล้ว +2

      What's wrong with this? Looks quite good to me. I am no C++ programmer though

    • @mishaerementchouk
      @mishaerementchouk ปีที่แล้ว +2

      @@jarvenpaajani8105 I'm not a developer, but the code does look peculiar. 'return's at the end of functions returning void; underscored members with "this" everywhere, "next_token" could be much shorter, say,
      try {t.type = type_from_char.at(byte_); t.literal = byte_; } catch (const std::out_of_range& unknown) {.. deal with it.. } read_char();
      where type_from_char is a respective map.
      Some stuff, such as 'final's, [[likely]], std::variant, I don't understand why it's needed, but, again, not a developer, maybe it improves performance.

    • @gregorssamsa
      @gregorssamsa 2 หลายเดือนก่อน

      The biggest problem is a lack of familiarity with the type system. Using a string is making copies of things everywhere. Using string view means the buffer exists once and then everyone has references into that same buffer. Many cases where this program would benefit from type parameters.

  • @JuusoAlasuutari
    @JuusoAlasuutari ปีที่แล้ว +1

    The fact is that CPP is the C pre-processor, which is the true pinnacle of elegance. C++ tried to beat the pre-processor's advanced feature set, failed miserably, and stole the name out of spite.

    • @isodoubIet
      @isodoubIet 5 หลายเดือนก่อน

      cringe

    • @JuusoAlasuutari
      @JuusoAlasuutari 5 หลายเดือนก่อน

      ​@@isodoubIet sad to hear about your condition

    • @isodoubIet
      @isodoubIet 5 หลายเดือนก่อน +1

      @@JuusoAlasuutari Didn't realize vegetables were capable of emotion

    • @JuusoAlasuutari
      @JuusoAlasuutari 4 หลายเดือนก่อน +1

      @@isodoubIet happy to hear about your realization

  • @blazefirer
    @blazefirer ปีที่แล้ว +1

    tom modCheck

  • @MoolsDogTwoOfficial
    @MoolsDogTwoOfficial 10 หลายเดือนก่อน

    std::for_each(comment.begin(), comment.end(), [](const char c) { std::cout

    • @MoolsDogTwoOfficial
      @MoolsDogTwoOfficial 4 หลายเดือนก่อน

      @lepingouindefeu Thank god I use C# now lol (I’ve become a product of Microsoft)