C++ Weekly - Ep 414 - C++26's Placeholder Variables With No Name

Поділитися
Вставка
  • Опубліковано 4 лют 2024
  • ☟☟ Awesome T-Shirts! Sponsors! Books! ☟☟
    Upcoming Workshop: Understanding Object Lifetime, C++ On Sea, July 2, 2024
    ► cpponsea.uk/2024/sessions/und...
    Upcoming Workshop: C++ Best Practices, NDC TechTown, Sept 9-10, 2024
    ► ndctechtown.com/workshops/c-b...
    Wondering how the C++ ecosystem is doing in 2023?
    C++20 is the base dialect.
    Python is the number one companion to C++.
    The C++ toolset has remained stable in recent years.
    Clang-based tools are growing in adoption.
    Discover more JetBrains Developer Ecosystem results: jb.gg/deveco_cpp23
    Use `CppWeeklyCLion` to get 25% OFF when you purchase a new CLion subscription or renew your existing one.
    Episode details: github.com/lefticus/cpp_weekl...
    T-SHIRTS AVAILABLE!
    ► The best C++ T-Shirts anywhere! my-store-d16a2f.creator-sprin...
    WANT MORE JASON?
    ► My Training Classes: emptycrate.com/training.html
    ► Follow me on twitter: / lefticus
    SUPPORT THE CHANNEL
    ► Patreon: / lefticus
    ► Github Sponsors: github.com/sponsors/lefticus
    ► Paypal Donation: www.paypal.com/donate/?hosted...
    GET INVOLVED
    ► Video Idea List: github.com/lefticus/cpp_weekl...
    JASON'S BOOKS
    ► C++23 Best Practices
    Leanpub Ebook: leanpub.com/cpp23_best_practi...
    ► C++ Best Practices
    Amazon Paperback: amzn.to/3wpAU3Z
    Leanpub Ebook: leanpub.com/cppbestpractices
    JASON'S PUZZLE BOOKS
    ► Object Lifetime Puzzlers Book 1
    Amazon Paperback: amzn.to/3g6Ervj
    Leanpub Ebook: leanpub.com/objectlifetimepuz...
    ► Object Lifetime Puzzlers Book 2
    Amazon Paperback: amzn.to/3whdUDU
    Leanpub Ebook: leanpub.com/objectlifetimepuz...
    ► Object Lifetime Puzzlers Book 3
    Leanpub Ebook: leanpub.com/objectlifetimepuz...
    ► Copy and Reference Puzzlers Book 1
    Amazon Paperback: amzn.to/3g7ZVb9
    Leanpub Ebook: leanpub.com/copyandreferencep...
    ► Copy and Reference Puzzlers Book 2
    Amazon Paperback: amzn.to/3X1LOIx
    Leanpub Ebook: leanpub.com/copyandreferencep...
    ► Copy and Reference Puzzlers Book 3
    Leanpub Ebook: leanpub.com/copyandreferencep...
    ► OpCode Puzzlers Book 1
    Amazon Paperback: amzn.to/3KCNJg6
    Leanpub Ebook: leanpub.com/opcodepuzzlers_book1
    RECOMMENDED BOOKS
    ► Bjarne Stroustrup's A Tour of C++ (now with C++20/23!): amzn.to/3X4Wypr
    AWESOME PROJECTS
    ► The C++ Starter Project - Gets you started with Best Practices Quickly - github.com/cpp-best-practices...
    ► C++ Best Practices Forkable Coding Standards - github.com/cpp-best-practices...
    O'Reilly VIDEOS
    ► Inheritance and Polymorphism in C++ - www.oreilly.com/library/view/...
    ► Learning C++ Best Practices - www.oreilly.com/library/view/...
  • Наука та технологія

КОМЕНТАРІ • 106

  • @steelrazor4782
    @steelrazor4782 4 місяці тому +113

    Wow _ for real? I was fully expecting std::placeholder or some shit like that.

    • @CramBL
      @CramBL 4 місяці тому +41

      _ is sugar for template constexpr inline std::variable_binding_placeholder

    • @corpseopera
      @corpseopera 4 місяці тому +1

      Best comment

    • @emiliancioca
      @emiliancioca 4 місяці тому

      yup hahah I was expecting the 100% same

    • @sinom
      @sinom 4 місяці тому +3

      Would have probably been std::ignore instead of std::placeholder, since std::ignore is how you did placeholders with std::tie before tuple destructuring was introduced. I really hope std::ignore can actually just be replaced with _ now in code that uses std::tie
      Edit: to add to this std::placeholder::_n is a really cool feature of std::bind that allows you to basically reorder function arguments as you like.

  • @TheClonerx
    @TheClonerx 4 місяці тому +52

    This is very useful for locks, and other RAII wrappers of similar nature where the actual value is not as important as the object lifetime

  • @_noisecode
    @_noisecode 4 місяці тому +20

    According to the paper, a declaration of _ also gets an implicit [[maybe_unused]] attribute, making `auto _ = foo();` a new, probably better way to write `static_cast(foo());` for explicitly discarding a function return value (and suppressing any related warnings).
    Obligatory to mention that this is the same approach Rust takes, where `let _ = foo();` explicitly silences warnings when ignoring the return value of a `#[must_use]` function.

    • @ALivingDinosaur
      @ALivingDinosaur 4 місяці тому +5

      `auto _ = foo();` and `static_cast(foo());` have different effect on the lifetime of the object returned by `foo()`.

  • @darkmagic543
    @darkmagic543 4 місяці тому +3

    I am really glad it is only allowed for the _ underscore and not all variable names, got spooked there for a bit.

  • @sinom
    @sinom 4 місяці тому +2

    This has been something I've used a LOT in other languages so it's great that we'll finally get a real placeholder in c++ soon™️

  • @PaulMetalhero
    @PaulMetalhero 4 місяці тому +16

    I wish they can deliver the final version of the reflection library for C++26

    • @sinom
      @sinom 4 місяці тому +2

      According to herb Sutter's summary of the last meeting that seems to be the plan right now but they haven't 100% finalized it just yet, same with SIMD and contracts.
      Basically unless anything guess wrong it will be in C++26, but they don't want to make any guarantees just yet

    • @PaulMetalhero
      @PaulMetalhero 4 місяці тому

      great news, thanks@@sinom

  • @constexprDuck
    @constexprDuck 4 місяці тому +5

    I think it's quite 'poggers' I dare say!

  • @EliteTester
    @EliteTester 4 місяці тому +2

    I can't wait to use this in 2032!

  • @andrewpaxie5264
    @andrewpaxie5264 4 місяці тому +1

    Time to figure out how this interacts with the wildcard variable in the trompeloeil mock object library. I have learned things don't usually go well by default.

  • @PaulTopping1
    @PaulTopping1 4 місяці тому +2

    It's a cool feature. Makes me think there should be a lot of use cases of '_' that should produce a warning or error but perhaps they would get in the way of legitimate uses. And the C++ philosophy is that erroneous uses of a feature should be allowed as long as they would only be created on purpose and would be very unlikely to be encountered by a C++ newbie.

  • @natekemp42
    @natekemp42 4 місяці тому +2

    How about a way to use this as a placeholder in a function call for “out” arguments (by refs or by ptr) whose values I don’t care about preserving or accessing after the function returns? This would allow for much cleaner code by avoiding the need to explicitly declare new local variables just to pass them to a function and then do nothing else with them.

  • @314Labs
    @314Labs 4 місяці тому +8

    Interesting that you can use "-std=c++26". I expected something like "c++2c" instead.

    • @von_nobody
      @von_nobody 4 місяці тому

      Standard now have stable release dates, no more `c++0x` that grow to `c++11` (10y from prev standard). But side effects is if some thing is not ready, it will be cut-out from next release (that already happens couple of times like `c++14` that miss couple features that was planed for it).

    • @Nobody1707
      @Nobody1707 4 місяці тому +2

      @@von_nobody GCC allows `-std=c++2c` as an alias for `-std=c++26`, but Clang requires the lettered version, and will until after the final draft is published if the way they handled C++23 was any indication. (Clang 17 and under require `-std=c++2b`)

  • @kuhluhOG
    @kuhluhOG 4 місяці тому +21

    Hey, this makes this possible now:
    #include
    template
    struct Deferer
    {
    ~Deferer()
    {
    T t;
    t();
    }
    };
    #define defer(code) auto _ = Deferer()
    int add(int a, int b)
    {
    return a + b;
    }
    int main()
    {
    defer(std::cout

    • @BSOD.Enjoyer
      @BSOD.Enjoyer 4 місяці тому +3

      you probably want defer macro to take ..., not defer (code)
      #define defer(...) auto _ = Deferer()
      otherwise everything after first non parenthesized comma is cut off
      example defer(std::cout

    • @kuhluhOG
      @kuhluhOG 4 місяці тому

      @@BSOD.Enjoyer probably, I don't really write a lot of macros

  • @DART2WADER
    @DART2WADER 4 місяці тому +8

    We need reflection! )))) We'll write the rest ourselves))

    • @AnthonyDentinger
      @AnthonyDentinger 4 місяці тому +1

      Can you elaborate on this? I fail to see the link between static reflection and a placeholder name.

    • @DART2WADER
      @DART2WADER 4 місяці тому +1

      @@AnthonyDentinger The Placeholder is good, but it's not as necessary as other things in the core of the language. Which cannot be implemented by writing libraries without third-party code generation utilities.

    • @not_ever
      @not_ever Місяць тому

      @@DART2WADER This isn't how the standards commitee works. You don't not get reflection because something else gets in. There are multiple groups working on different things. It's not a single thread operation.

  • @Minty_Meeo
    @Minty_Meeo 4 місяці тому +2

    So it's shadow declarations as a feature. Neat.

  • @peessinitro1395
    @peessinitro1395 4 місяці тому +4

    Can you please make a Video on the use-cases of C++26 hazard_pointer and why not to just use a shared_ptr? Thanks.

    • @aniketbisht2823
      @aniketbisht2823 4 місяці тому

      Using Hazard pointers instead of std::atomic can leads to significant performance increase as usage of hazard pointers require mostly wait-free instructions that makes it's performance agnostic to number of readers so it scale perfectly with scenario involving many readers but few writers.
      Hazard Pointers tend to be hard to use (it's basically a garbage collection scheme) so there's that trade-off.

    • @peessinitro1395
      @peessinitro1395 4 місяці тому

      @@aniketbisht2823 Is the performance difference really this massive to considee using that over the other?

    • @aniketbisht2823
      @aniketbisht2823 4 місяці тому

      @@peessinitro1395 If you are sure that your algorithm/(process using this DS) is not gonna use more than, lets say 8 threads, then I guess it would be fine, but parallel code is seldom written with that mindset. You expect your parallel algorithm to scale perfectly from N=1 to N=128 or more.
      Ref-counting can kill the performance of std::atomic even if multiple threads just read it (access it) frequently and it's not modified, whereas schemes like Hazard pointer and RCU (Read-Copy-Update) are reader agnostic when it comes to scalability.
      You should watch Fedor Pikus's talk on RCU. He goes in depth about the implementation and shows benchmarks. You need to be familiar with atomics and C++ memory model to understand the implementation.
      I have taken inspiration from RCU/Harzard-Pointers and now I am working on my own data-structure for deferred reclamation which is even more constrained and hence simpler to implement and more performant (I hope).

    • @cppweekly
      @cppweekly  4 місяці тому

      I have a site for everyone to add their topic requests so I don't lose them in the comments - feel free to add your ideas and vote on other's ideas here: github.com/lefticus/cpp_weekly/issues/

  • @j777
    @j777 4 місяці тому +2

    Just like ~ in Matlab :)

  • @jhbonarius
    @jhbonarius 4 місяці тому +6

    At the end you say it "hides" the previous declaration, but it doesn't, right? As as soon as you try to use it after the second declaration, you get the ambiguous declaration error. So it's not hidden, as in replaced: it's still there.

    • @basilefff
      @basilefff 4 місяці тому

      I think in the proposal it's supposed to just allow you to use the first declaration as if it was an actual variable, and those that come after are shadowed instead. I think Jason has -Werror enabled

    • @aniketbisht2823
      @aniketbisht2823 4 місяці тому +1

      @@basilefff No. If there are more than one _ variables in the same scope the program will be ill formed. But if you introduced another scope and declare a single _ in that scope that shadows _ of the outer scope then you can use it.

    • @basilefff
      @basilefff 4 місяці тому

      @@aniketbisht2823 Oh, my bad, was reading old version of the paper.

  • @alskidan
    @alskidan 4 місяці тому +2

    This time the avatar is sucking his index finger 😂 How can I unsee this? 😅

  • @PedroOliveira-sl6nw
    @PedroOliveira-sl6nw 4 місяці тому

    What about using that in classes and the -Wshadow warning?

  • @robertfrysch7985
    @robertfrysch7985 4 місяці тому +1

    I like it

  • @katanasteel
    @katanasteel 4 місяці тому

    Is this like function overloading... but with variables?

  • @LesleyLai
    @LesleyLai 4 місяці тому +6

    Finally! Of course, C++ always has its own quirks, but it is still a valuable feature

    • @aDifferentJT
      @aDifferentJT 4 місяці тому +12

      Doing it this way is nice because it preserves backwards compatibility with source that might have used _ as a variable name.

    • @BaardFigur
      @BaardFigur 4 місяці тому +3

      ​@@aDifferentJTWould still be nice if there was a warning that catches this

  • @cgerman
    @cgerman 4 місяці тому

    Isn't std::ignore supposed to be used when you don't care about the variable?

  • @phildem414
    @phildem414 4 місяці тому +1

    I really have a hard time thinking of this is a good thing, let's think of the concequences on junior developers a minute. Isn't it a open door to even more criptict error messages?
    What is the impact on compilation time?

    • @basilefff
      @basilefff 4 місяці тому +2

      I think it's not that complicated a feature for anyone to use. Also, why would compilation time be affected much or at all? I am not sure about cryptic error messages, that actually may be a problem

    • @ALivingDinosaur
      @ALivingDinosaur 4 місяці тому

      This feature will end the frustration of inventing names for objects of `std::lock_guard` and similar RAII types.

    • @cppweekly
      @cppweekly  3 місяці тому

      I really think it's only potentially useful in the case of structured bindings

  • @eggmeister6641
    @eggmeister6641 4 місяці тому

    This. This so much.

  • @Key_Capz_
    @Key_Capz_ 13 днів тому

    Are there any books on c++26 yet?

  • @anon_y_mousse
    @anon_y_mousse 4 місяці тому

    This is good news, but I actually thought they had already added this in a prior version and waiting until 26 is annoying.

  • @rafi1082
    @rafi1082 4 місяці тому +1

    They got that from python

  • @BenUK1
    @BenUK1 4 місяці тому +1

    I thought you could already use std::ignore to ignore values that you weren't interested in?

    • @_noisecode
      @_noisecode 4 місяці тому

      std::ignore is designed to work with std::tie(), where you are assigning already-declared values. It doesn't work with structured bindings or variable declarations.

    • @BenUK1
      @BenUK1 4 місяці тому

      @@_noisecodeGood to know, thanks. It sounds like I've been using it wrong then... I've used it in a couple of places when I've wanted to discard the result from a [[nodiscard]] function (Where the function should never have been NoDiscard, in my opinion.).

    • @_noisecode
      @_noisecode 4 місяці тому +1

      ​@@BenUK1 Er yeah, that's definitely a valid use case too actually! The original std::ignore motivation was indeed to help with std::tie, but you're right, it does also provide a nice clean alternative to static_cast() for discarding [[nodiscard]] return values at the top level. It still doesn't play nicely with structured bindings though.

  • @groaningmole4338
    @groaningmole4338 4 місяці тому

    Yet another convenience feature that will add a whole bunch of extra rules to the language.
    We are already wading through too many new rules and exceptions to rules.

  • @blazkranjc91
    @blazkranjc91 4 місяці тому +4

    It would be so much better if the compiler had a way to ensure "_" is never used and force a name when it is. This makes "_" a new half-blood magic construct.

    • @yato3335
      @yato3335 4 місяці тому

      Unfortunately, they can't do that because that would break backwards compatibility.

    • @kethernet
      @kethernet 4 місяці тому

      I could see deprecating and eventually removing actually using "_", but at least initially, it wouldn't be good to break existing code that might use it.

    • @mridgewell
      @mridgewell 4 місяці тому +2

      I wouldn't be surprised if there's a new clang-tidy warning soon to detect uses of variables named `_`

    • @BaardFigur
      @BaardFigur 3 місяці тому

      ​@@yato3335 Could've added a warning for it at least, though

  • @snorrikristjansson7013
    @snorrikristjansson7013 4 місяці тому +1

    I get that this is useful - but IMHO using an "_" variable should be an error in the language. Why would you want to declare something as "unused" by using the special "_" var and then later use it in your code?

    • @Y2B123
      @Y2B123 4 місяці тому

      For backward compatibility of codes that use the variable _ normally. Now that this is a feature, you really shouldn't use it.

    • @BaardFigur
      @BaardFigur 3 місяці тому

      How about usage of the macro define _(str) gettext(str)?

  • @nmmm2000
    @nmmm2000 4 місяці тому +3

    will it work with any name?
    int a = 5;
    int a = 6;

    • @eLBehmo
      @eLBehmo 4 місяці тому +1

      no

    • @nmmm2000
      @nmmm2000 4 місяці тому

      @@eLBehmo wait, just for underscore??? really??? what makes underscore special?

    • @CryZe92
      @CryZe92 4 місяці тому

      @@nmmm2000 It seems like it's mostly for backwards compatibility, so all old code still behaves the same way, but since they want to have _ be a special placeholder, they do it as a special identifier that can be shadowed.

  • @LunarLambda
    @LunarLambda 4 місяці тому +10

    That's the most C++ way solution imaginable. Instead of being a new syntactical construct it's now a magic identifier you can sometimes maybe use. Instead of being a discard pattern like in Rust

    • @TheClonerx
      @TheClonerx 4 місяці тому +5

      Most languages do it this way, see Rust and Python for example

    • @kuhluhOG
      @kuhluhOG 4 місяці тому +7

      well, kinda what you have to do when you don't want to break existing code
      I don't know why people just randomly use _ as an identifier, but some do, not for discarding it too.

    • @germanassasin1046
      @germanassasin1046 4 місяці тому +1

      @@kuhluhOGmaybe they at first used this as a discard patter but suddenly needed this value, so they used it and were too lazy to rename it. And while this is a shitty thing to do, I can totally see this happening

    • @Nobody1707
      @Nobody1707 4 місяці тому +1

      Unfortunately a number of libraries use _ as an identifier for something other than a `std::ignore` equivalent so this was the best they could do without using double underscores as the discard pattern.

    • @CryZe92
      @CryZe92 4 місяці тому +1

      @@TheClonerx Rust does not do it this way. It's not an identifier.

  • @VladykaVladykov
    @VladykaVladykov 4 місяці тому +1

    Получается, не std::ignore

  • @MenaceInc
    @MenaceInc 4 місяці тому +2

    Naming is hard so now you don't have to!

  • @dannywidjaya7943
    @dannywidjaya7943 3 місяці тому

    use dot

  • @aportabales
    @aportabales 4 місяці тому

    Bugs are coming in 2026

  • @yato3335
    @yato3335 4 місяці тому +1

    I wish that the values would be destroyed when you redeclare the underscore variables. It would allow for rust-like drop semantics.

    • @vytah
      @vytah 4 місяці тому +1

      Rust doesn't drop objects held by variables when those variables are redeclared, they live till the end of the scope like normal.

    • @yato3335
      @yato3335 4 місяці тому

      @@vytah is that so? What if the name redeclares the variable for the remainder of the function body? I thought that rust drops objects as soon as they become unreachable.

    • @vytah
      @vytah 4 місяці тому

      @@yato3335 Not being nameable doesn't mean unreachable. There might be other ways to reach the first object, e.g. via a reference created between the two objects, or the first object might be used by the second object. Unless the first object is destroyed first by moving from it (with for example std::drop), they are dropped in the reverse declaration order, like in C++.

    • @yato3335
      @yato3335 4 місяці тому

      @@vytah makes sense, didn't think about it

  • @xbylina2641
    @xbylina2641 4 місяці тому

    _, println... So, C++ tries to become Rust...

    • @germanassasin1046
      @germanassasin1046 4 місяці тому +3

      I remember println from way back in pascal era. and _ thingy is used as long as programming languages existed. rust has nothing to do with those

  • @throwaway3227
    @throwaway3227 4 місяці тому

    Does this mean that warnings for unused variables are put back in for C++26, or is this another feature copied from Rust on such a surface level that it doesn't bringing the real benefits?

    • @cppweekly
      @cppweekly  3 місяці тому

      I could see it possibly being added back in for unused portions of a structured binding, specifically, but that will be a compiler implementation detail.

  • @WakeUp4L1fe
    @WakeUp4L1fe 4 місяці тому +1

    It's a shame that I have to wait a couple of years for a feature to be implemented into the language, and then a couple of years for the C++ standard to make it into the C++ project itself.

    • @treyquattro
      @treyquattro 4 місяці тому

      by which time ChatGPT will be doing your job anyway...

  • @janwilmans5954
    @janwilmans5954 3 місяці тому

    Very interesting to see that my proposal that never made it into a meeting, has been implemented ;)
    github.com/janwilmans/janwilmans.github.io/blob/master/auto.md

  • @TsvetanDimitrov1976
    @TsvetanDimitrov1976 4 місяці тому

    I imagine this change will break a lot of code

    • @DerAlbi
      @DerAlbi 4 місяці тому +6

      If so, its deserved. Well actually, probably not. Usage of _ is probably only ambiguous if there are more than one _. Up until now, just 1 _ may exist per scope. Therefore, if used only once, _ may be a valid variable name, if used more than once it is the anonymous _.

    • @TsvetanDimitrov1976
      @TsvetanDimitrov1976 4 місяці тому

      @@DerAlbi i use it mainly for lock guards or temporary intermidiate values, but it seems it's scoped, so shouldn't be a big problem

    • @peterfordham3562
      @peterfordham3562 4 місяці тому +2

      Can you give a simple example.of code that it will break?

    • @TsvetanDimitrov1976
      @TsvetanDimitrov1976 4 місяці тому

      @@peterfordham3562 not really. as long as it it's scoped it should be fine. any code that uses multiple _ in the same scope is already broken.

    • @kethernet
      @kethernet 4 місяці тому +8

      How so? It's currently a compiler error to declare two variables with the same name in the same scope. This change accepts strictly more sources.

  • @truesoundwave
    @truesoundwave 4 місяці тому

    Why would anyone want to do something like this?

  • @ProGaming-kb9io
    @ProGaming-kb9io 4 місяці тому +2

    I really hate this language :)