C++ Weekly - Ep 306 - What Are Local Functions, and Do They Exist in C++?

Поделиться
HTML-код
  • Опубликовано: 15 сен 2024

Комментарии • 52

  • @benjaminnavarro865
    @benjaminnavarro865 2 года назад +34

    With the struct at the beginning, you could skip the extra parenthesis by instantiating an anonymous struct:
    int main() {
    struct {
    int operator()() {
    return 42;
    }
    } get_value;
    return get_value();
    }

    • @reubenfrench6288
      @reubenfrench6288 2 года назад

      That isn't standard; it's a language extension supported by some compilers.

    • @benjaminnavarro865
      @benjaminnavarro865 2 года назад

      @@reubenfrench6288 Which part is non-standard? It works with GCC, Clang and MSVC but anyway, that's just a fun experiment, not something you should write. Lambdas are the way to go

    • @reubenfrench6288
      @reubenfrench6288 2 года назад

      @@benjaminnavarro865 Anonymous structs are non-standard, but anonymous unions are.

    • @michaelmahn4373
      @michaelmahn4373 2 года назад +3

      Anonymous structs aren't allowed, but this is not an anonymous struct. This is an unnamed struct. They are allowed.

    • @reubenfrench6288
      @reubenfrench6288 2 года назад

      @@michaelmahn4373 Interesting. TIL.

  • @nmmm2000
    @nmmm2000 2 года назад +13

    To be more readable, I usually make a variable with lambda, then give it to the algorithm:
    auto comp = [](const auto key){ return key < 42; };
    auto it = std::find(std::begin(v), std::end(v), comp);

    • @cppweekly
      @cppweekly  2 года назад +3

      Definitely, I do that more and more in real code now, it's also how I teach in my Best Practices classes.

  • @ysakhno
    @ysakhno 2 года назад +10

    You forgot to mention that 'true' local functions can capture local variables

  • @Xilefian
    @Xilefian 2 года назад +3

    What a coincidence, I happened to have been reading about the GCC local functions extension a couple days ago thinking “woah, I don’t know anyone who has talked about this”

    • @cppweekly
      @cppweekly  2 года назад

      I probably should have covered extensions... but it's not really a world I live in, for the sake of portability.

  • @vladigr1
    @vladigr1 2 года назад +2

    it remind me the streams of Bob Ross when there are comments like " 50 % he is going to draw a cabin" and the chat go wild but in Jason case its "50% he is going to write a lambda".

  • @warrenbuckley3267
    @warrenbuckley3267 2 года назад +3

    Lambdas are great and all but I do like local functions. C# introduced local functions a few years ago and I really like it (I personally find it looks cleaner).

  • @apenasmeucanal5984
    @apenasmeucanal5984 2 года назад

    auto func(Args&&... args) -> ReturnType { }
    auto func = [ ](Args&&... args) -> ReturnType { };
    pretty much the same in practice, although doing different things. i’d say it’s not a stretch stating that local functions can exist through lambdas, that’s very intuitive...

  • @von_nobody
    @von_nobody 2 года назад +2

    GCC C compiler have extension Nested-Functions that allow this, interesting they have similar functionality to `[&]` lambda as can reference objects from parent function

    • @platin2148
      @platin2148 2 года назад

      You don’t mean the block extension do you?

    • @embeddor2230
      @embeddor2230 2 года назад

      It's very unsafe though, even if you don't reference stuff from the parent's scope.

    • @RobertFisher1969
      @RobertFisher1969 2 года назад

      @@platin2148 GCC’s local functions extension is different from (and, I think, predates) the block extension.

    • @scarletlettersproductions4393
      @scarletlettersproductions4393 2 года назад

      @@platin2148 blocks is clang's extension and is much closer to actual lambda functions we have in C++. It has different syntax from normal functions (somewhat similar to function pointer syntax), the data is stored either statically or on the heap, and the function part is just treated like a normal function, so there are no security issues like with GCC's Nested Functions.
      Nested Functions in GCC have the same syntax as normal functions and basically store a closure in the current stack frame and make the stack executable (which is why they're dangerous)

    • @0xCAFEF00D
      @0xCAFEF00D 2 года назад

      @@embeddor2230 What is unsafe about it? All I've read is that you can take the address and call if from anywhere, accessing stack variables after they're out of scope. Which is dangerous but it's as expected as referencing any local variable after its scope.

  • @TheSulross
    @TheSulross 2 года назад +1

    there are some languages that do support local functions (e.g., some dialects of Pascal) but. i find C++ lambdas a superior alternative as can specify the exact manner of closure over outer scope variables of the host function body - which is ay safer than just some sort of defaulting to closure over every outer scope variable in some generic manner of semantics - C++ allows specifying either value or reference semantics
    once something resembling local functions exist it really needs to have offer up control over manner of outer scope closure or else is just another gun that will end up shooting a foot off

    • @TrueWodzu
      @TrueWodzu Год назад

      Except that in Pascal you can store function pointer to capturing "lambda" and in C++ you can't, which I think makes them inferior to Pascal ones. You can also have a non-capturing nested functions that will have access to all previously declared variables in the parent function. I find funny that you are commenting about shooting a foot off, because C++ is literally the number one language in that regard.

  • @MeeroSom
    @MeeroSom 2 года назад

    nice, Jason, please talk to us furthermore aka dont stop this

  • @victoreijkhout6146
    @victoreijkhout6146 2 года назад +1

    None of your non-lambda solutions attempted to use variables in their defining scope act as globals. Fortran statement functions definitely did this. I don't remember about Pascals nested functions. The lambda capture also solves this problem.

    • @nextlifeonearth
      @nextlifeonearth 2 года назад

      I'm wondering what the difference even is, besides syntax, between lambdas and local functions.

  • @9uiop
    @9uiop 2 года назад +1

    What is the point of allowing local function declarations then, if they cannot be defined?

    • @Qazqi
      @Qazqi 2 года назад +2

      They can be defined, but only in the surrounding scope. For example:
      int main() {
      void foo();
      foo();
      }
      void foo() {}
      I still find little point to this, especially with the tradeoff that allowing this is what gives rise to MVP, but it isn't a dead end.

    • @RobertFisher1969
      @RobertFisher1969 2 года назад

      I don’t think there was ever a point to it, per se. Allowing it was just a side-effect of the grammar, and there was no reason to explicitly disallow it.

  • @fromgermany271
    @fromgermany271 2 года назад

    I used lambda that way since they are available.

  • @DamianReloaded
    @DamianReloaded 2 года назад

    Lambdas are cool. I use them quite a bit for things I need to do more than once inside a method.

  • @garyp.7501
    @garyp.7501 2 месяца назад

    Boost Lambda could do this in C++98..... using template meta programming...

  • @petermuller608
    @petermuller608 2 года назад

    The lack of local functions bugged me a lot coming from pascal to different languages. Fortunately most languages fixed this with the introduction of lambdas

  • @peterevans6752
    @peterevans6752 2 года назад

    Why did you suggest local functions are being considered for C++23? Is it something to do with co-routines or immediate functions?

    • @cppweekly
      @cppweekly  2 года назад

      I don't actually recall suggesting that.

  • @antonfernando8409
    @antonfernando8409 2 года назад

    And if I understood right, these lambas's captures and their states are persistent, so even though we may exit the function scope, upon next entry to the function the lamba and reuse its captured captures states.

    • @X_Baron
      @X_Baron 2 года назад +1

      If you capture by reference, you must be careful to ensure that lifetimes of the referenced variables don't end. Calling a lambda with a dangling reference results in undefined behavior. If you capture by value, the captured values do stay with the lambda as long as it exists.

    • @antonfernando8409
      @antonfernando8409 2 года назад

      @@X_Baron cool.

  • @zimi992
    @zimi992 2 года назад

    Is there any advantage for local functions compared to lambdas?

    • @cppweekly
      @cppweekly  2 года назад

      Well, in C++ local functions don't really exist, so your main option is to use a lambda, or to emulate one with a local class, like I demonstrate.

  • @khatharrmalkavian3306
    @khatharrmalkavian3306 2 года назад

    Haven't watched yet, but I just wanted to pause and start out by saying that I LOVE embedding unexpected things in function scopes. It makes people so angry!

  • @fcolecumberri
    @fcolecumberri 2 года назад

    "We are not allow to use a local class as a tamplate parameter... what a pain in the rear"
    jason turner at his finest

    • @cppweekly
      @cppweekly  2 года назад

      You have no idea how many times I used to get that error back when I was first learning C++ and trying to take advantage of algorithms!

  • @khatharrmalkavian3306
    @khatharrmalkavian3306 2 года назад

    Yeah... Allowing the call operator to be static seems like a bad idea that would break everything and only be useful for implementing bad ideas....
    I mean I'm open to hearing examples, but to be honest that's just because I'm certain to get a laugh out of it.

  • @bochkarevartem
    @bochkarevartem 2 года назад +1

    Local functions(and lambdas) are overused very often. Separate functions with good names makes code better to read and understand.

    • @Qazqi
      @Qazqi 2 года назад +5

      That's what local functions do. They separate something out into a new function with its own name that a) doesn't clutter the surrounding scope if it's only used in one place; and b) doesn't require a bunch of boilerplate to pass in local state.

    • @mocloun3709
      @mocloun3709 2 года назад +1

      @@Qazqi But still, separate functions make code better to read and understand because you are not littering the main function.

    • @cppweekly
      @cppweekly  2 года назад +1

      It can go both ways. Having a bunch of single-use functions that are in global scope can also make code harder to reason about. The hard part is finding the mix that works best.

  • @hsavietto
    @hsavietto 2 года назад +1

    Jason has a little lambda