36

I think the following code is very handy and no harmful:

auto fn = [](bool b = false) -> int // NOT legal in C++11
{
    return b ? 1 : 0;
}; 

Why does C++11 explicitly prohibit default arguments of the lambda expression?

I just wonder the rationales and considerations behind.

I want to know "WHY" rather than "WHAT" the C++11 standard says.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • 2
    Because, technically, it's an overload (I'm not sure if this word is correct here, but you get the idea): You can call it with a bool, or without one. What should be the *type* of the lambda function in this case? When designing lambdas, they didn't want to introduce lambda types which can have a variable number of arguments (0 or 1 in your case) – leemes Jan 07 '13 at 03:46
  • 3
    "WHY" is that code very handy and no harmful? (since we're asking why here). – WhozCraig Jan 07 '13 at 03:49
  • 1
    @leemes: Doesn't quite fit. `void f(int x=0);` does not technically involve overloading, and the type of `f` is definitely `void(int)`. – aschepler Jan 07 '13 at 03:49
  • 1
    What use is there for this? From what I can think of off the top of my head, something is always going to be calling it with the same number of arguments as a callback, whether when an event occurs, or in the case of something like `std::for_each`. Could you give an example of how it would be useful for something? – chris Jan 07 '13 at 03:51
  • @aschepler That's why I said I'm not sure with the word here. I was almost sure that it's not an overload. But it's similar. `f` can be called like it *was* an overloaded function, but it *isn't*. So its type is `void(int)`, but it can also be called like it was `void()`. Other functions, like `void g(int x)`, can *not*. And we have to annotate this in the type of the lambda expression, otherwise it can't be called without an argument. That's what I wanted to put in fewer words ;) – leemes Jan 07 '13 at 03:52
  • 9
    For what it's worth, lambdas are really just anonymous functors, and functors can have default arguments. It's interesting that lambdas wouldn't. – chris Jan 07 '13 at 03:55
  • @chris: Well, no, that's not really true. There are many real-world situations where a "functor" defined inside a function can't be used, however, a lambda can be used in those situations. – Dietrich Epp Jan 07 '13 at 03:57
  • @DietrichEpp Do you have an example? – leemes Jan 07 '13 at 03:58
  • @DietrichEpp, Isn't it defined outside of the function, though, or am I getting into implementation details now? – chris Jan 07 '13 at 03:58
  • 1
    How does `std::function` treat functions with default arguments? – Seth Carnegie Jan 07 '13 at 03:59
  • @leemes: If you define a functor inside a function it can't be used as a template parameter, which makes it near worthless. – Dietrich Epp Jan 07 '13 at 03:59
  • @chris I think both is possible, at least I remember we can define new structs in functions, so why not functors. – leemes Jan 07 '13 at 03:59
  • @SethCarnegie I don't think it can. (*Think* emphasized). – leemes Jan 07 '13 at 04:01
  • @SethCarnegie, http://stacked-crooked.com/view?id=7865a193b81071bd18742213bb389e86 – chris Jan 07 '13 at 04:02
  • @DietrichEpp Ok but what if I define it outside of the function? – leemes Jan 07 '13 at 04:02
  • 2
    @DietrichEpp C++03 did not allow local types to be used as template type arguments, but I believe C++11 removed that restriction. – aschepler Jan 07 '13 at 04:03
  • @chris so it treats them as if the optional arguments were required, I thought so. As for the question, not sure why except either oversight or wanting to keep things simple. – Seth Carnegie Jan 07 '13 at 04:03
  • @chris Even with function pointers: http://stacked-crooked.com/view?id=f13fc744148f3b7bd07ed41adf36ac4a – leemes Jan 07 '13 at 04:04
  • @leemes: Then you don't have access to variables in the function's scope. That's the whole point of lambdas: they give you access to variables in the enclosing function's scope. – Dietrich Epp Jan 07 '13 at 04:04
  • @DietrichEpp I always just put them in the constructor + store as member... (Which is of course also possible with references). Of course, there is no "catch all". – leemes Jan 07 '13 at 04:05
  • @DietrichEpp, Oh right, the capturing kind of screws up defining it outside of the function. – chris Jan 07 '13 at 04:06
  • @leemes: And then you don't have access to private members that the function can access. And you're making your code much more complicated. – Dietrich Epp Jan 07 '13 at 04:06
  • @DietrichEpp Ok I give up. Argument accepted. :) – leemes Jan 07 '13 at 04:07
  • 2
    @Dietrich : It's a moot point; aschepler is right – in C++11, templates arguments are no longer required to have linkage. – ildjarn Jan 07 '13 at 04:39
  • 2
    For what it's worth, the constraint about the default arguments in lambdas was removed in C++14: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#974 – J L Mar 26 '20 at 10:28
  • According to https://en.cppreference.com/w/cpp/language/lambda, that defect report retroactively applies to C++11, so even in C++11 default arguments are allowed in lambda expressions (although GCC 13.1 still warns on it) – user119879 May 22 '23 at 13:05

4 Answers4

26

There is no real reason that lambdas can't have default arguments. However, there are two main ways to use lambdas, and only one of them would allow default arguments without changing the type system.

  1. You can call the lambda directly, or through a template. Default parameters would work fine in this case.

  2. You can call the lambda through std::function. Default parameters would not work without changing the type system.

My guess is that new functions that people write in C++11 will usually take std::function parameters because this way, the function won't have to be a template, or it won't have to be instantiated for every single lambda and functor that gets passed to it.

Why can't a std::function (or function pointer) take defaults?

It's not obvious what the type of such a function would be.

  • If it's std::function<int(bool)>, then how do you call it with the defaults? (You can't.)

  • If it's std::function<int(bool=false)>, then what types is it compatible with, and how does conversion work? Can you convert it to std::function<int()>? What about std::function<int(bool=true)>?

  • If it's something new like std::function<int(bool=default)>, then what types is it compatible with, and how does conversion work?

Basically, this isn't just a switch you can flip in the standard and make function pointers / std::function handle default arguments. Default arguments in normal functions are handled using information from the function's declaration, which is not available at the call site for a lambda or function pointer. So you would have to encode information about the defaults into the function type, and then work out all of the non-obvious rules for conversion and compatibility.

So you would have to come up with a compelling case for why such a feature would be added, and convince the committee.

So, why can't lambdas take defaults?

I haven't answered this question. But I don't think it would be a very useful feature to add. I would delete this answer if I could, but it's been accepted. I would downvote it if I could, but it's mine. C'est la vie.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • Why isn't the information from the lambda's declaration available at the call site? – Seth Carnegie Jan 07 '13 at 04:22
  • 2
    @SethCarnegie: Because lambda functions don't have function declarations, they only have types. This also applies to any function which is called through a pointer. – Dietrich Epp Jan 07 '13 at 04:23
  • I can't remember exactly but isn't the type of a lambda some compiler-made type that isn't accessible outside the scope of the lambda? Couldn't the information be put there? I mean, a lambda is not a function pointer. – Seth Carnegie Jan 07 '13 at 04:26
  • 1
    @SethCarnegie: But it could be called from a completely different translation unit. Type information doesn't cross translation unit boundaries. – Dietrich Epp Jan 07 '13 at 04:27
  • Yeah, I was thinking lambdas had some special information where they were declared but they don't, evidenced by the fact that an `std::function` can store one. – Seth Carnegie Jan 07 '13 at 04:29
  • this doesnt convince me. default arguments are not part of the function type and hence the type would simply be int(bool). the function call operator of the lambda has a single synthesized declaration in which the default argument would be attached. can you explain further? – Johannes Schaub - litb Jan 07 '13 at 06:09
  • if the lambda is converted to a function pointer (when it has no captures), it is not anymore callable by using a default argument. that is true of any function that has a default argument. can you please provide a reference for your claim that this is the rationale seeked for? – Johannes Schaub - litb Jan 07 '13 at 06:12
  • 1
    @JohannesSchaub-litb: Don't get caught up on the bit about function pointers versus lambdas. The point is that a lambda is a value, so it doesn't have a declaration. Yes, the same is true of functions when they are converted to values (which have function pointer type). Since the type system does not encode default parameters, it is natural to conclude that extending the type system to encode default parameters would be required for adding default parameters to lambda. – Dietrich Epp Jan 07 '13 at 06:59
  • @JohannesSchaub-litb: It's a bit facile to ask for a citation for the rationale -- I have no evidence that the standards committee even considered the topic, and so I am merely providing a *possible* explanation. Let me repeat that: a possible explanation, not a rationale, since I am not assuming that the committee considered this topic. – Dietrich Epp Jan 07 '13 at 07:03
  • 2
    i am sorry but that just doesnt make sense at all. if you want to know why it doesn't make sense and want me to undo my downvote, you can ask a new SO question (it seems that my explanation in my comment is not elaborate enough). several ppl have pointed out that a lambda is "just" a class type function object that can have default arguments. – Johannes Schaub - litb Jan 07 '13 at 07:56
  • Perhaps a simpler way to get your head around the problem is to consider a default argument is syntactic sugar for writing two functions, one of which calls the other. So to do this with lambdas (or with function pointers) would involve storing all the information about two function signatures in the one lambda (or function pointer) type. Not impossible, but certainly a lot more complicated than it might first appear. – Zero Jan 07 '13 at 08:05
  • @JohannesSchaub-litb: I don't really need an explanation or a downvote removed. I know how it works, and I'd rather just delete the question. The argument was really based on the idea that the purpose for the lambda is to provide something like an anonymous functor that can be called from another translation unit, which means that my argument is really about `std::function` and not lambdas. – Dietrich Epp Jan 07 '13 at 09:30
  • `Default arguments in normal functions are handled using information from the function's declaration, which is not available at the call site for a lambda or function pointer. So you would have to encode information about the defaults into the function type, and then work out all of the non-obvious rules for conversion and compatibility.` That's the answer :) – Lightness Races in Orbit Jan 07 '13 at 13:02
  • @LightnessRacesinOrbit: I think availability of the defaults at the call site should not be an issue. For instance, a variable of type `std::function` can hold a pointer to a function `void foo(int x = 0)`: you will have to provide the argument when calling the function through `std::function`'s call operator, but you can omit it when calling `foo()` directly. Lambdas are just syntactic sugar for functors: as long as you assign your lambda to a value of type `auto`, you're fine with omitting arguments with a default. If you embed it in `std::function`, you shall pass them explicitly – Andy Prowl Jan 07 '13 at 16:38
  • @AndyProwl: Nope, even with `auto` that does not work, because _defaults are not part of the function type_. They are just syntactic sugar related to function declarations (your function `void foo(int x = 0)` is in fact merely a function `void foo(int x)`). Thus the declarations absolutely must be visible if you want to omit the defaulted argument. So what's the point in allowing the syntax for lambdas? You could pretty much never use it. – Lightness Races in Orbit Jan 07 '13 at 16:45
  • @LightnessRacesinOrbit: lambdas just define a hidden closure object, i.e. a functor with a call operator whose signature is basically identical to the signature of the lambda. so if the lambda has a default value, the signature of your closure's call operator will have it as well. and as long as you store your lambda in an `auto` variable, you will refer directly the hidden closure type with a call operator signature that does contain the default value declaration – Andy Prowl Jan 07 '13 at 16:49
  • @Andy: I know what lambdas are. Default arguments are still not part of the function signature (see 1.3.17). That doesn't change just because you hide the type behind `auto`. – Lightness Races in Orbit Jan 07 '13 at 16:50
  • @LightnessRacesinOrbit: I know they are not, but the question is precisely "why are they not?", and there is no technical reason why they should not be. in particular, there is no need to adapt the type system. – Andy Prowl Jan 07 '13 at 16:50
  • @Andy: Right, which is what absolutely everybody on this page (myself included) is saying. You'd have to adapt the type system, and there's no point. – Lightness Races in Orbit Jan 07 '13 at 16:51
  • @LightnessRacesinOrbit: actually I just wrote the opposite: "there is no need to adapt the type system" (meaning: you can introduce defaults without adapting the type system). and it's not true that everybody on this page is saying that (see comment by Johannes Schaub above). – Andy Prowl Jan 07 '13 at 16:54
  • @AndyProwl: Okay. Well _I_ am saying that and so is Dietrich, and we are both correct. :) The default arguments are not part of the function signature, nor the type, so if you wanted your call on an anonymous functor (that in the general case can be refered to only by a type and by a pointer) to be at all aware of default arguments, we would have to _add_ default arguments into function signatures. That's a gross change to the language with next to no benefit. That's why it wasn't done. – Lightness Races in Orbit Jan 07 '13 at 16:57
  • @LightnessRacesinOrbit: sorry but I find it hard to accept the argument "I say it -> It's correct" :) it would be enough to change the way the closure is generated (i.e. to include default arguments declared in the lambda in the closure's call operator's signature). Generating the hidden closure is just syntactic sugar and for defining a slightly different syntactic sugar you don't need to change the type system. – Andy Prowl Jan 07 '13 at 17:01
  • @Andy: "I say it -> it's correct" is sufficient at the end of this long and tiring comment thread ;) In seriousness, though, I've also provided plenty of non-sarcastic reasoning both here and in my answer. You keep ignoring it, though: `(i.e. to include default arguments declared in the lambda in the closure's call operator's signature)` **no**, because _default arguments are not part of a function signature_. Plain and simple. – Lightness Races in Orbit Jan 07 '13 at 17:04
  • @LightnessRacesinOrbit: I'm sorry, that's *never* a sufficient argument. I am not ignoring anything. I agree that defaults are not part of a signature. I don't agree on the fact that lambdas should be treated differently than any other function with defaults. There's just no reason. The argument in your answer fails at "and must be unambiguously visible to the call site". I never claim that. Yes, they would be visible only when invoked in the local scope through a variable whose type is inferred by means of `auto`. – Andy Prowl Jan 07 '13 at 17:10
  • @AndyProwl: It wasn't an argument; it was a very obvious joke. The rest of my comments and my answer are the argument. I feel no need to repeat it any further. I have backed up my claims with standard citations in my answer. – Lightness Races in Orbit Jan 07 '13 at 17:10
  • @LightnessRacesinOrbit: you have backed up the part of your claims which I have never meant to disprove. I know what's part of a function signature. Again, the argument in your answer fails at "and must be unambiguously visible to the call site". I never claimed that. But ok, I don't mean to force you to continue this discussion. – Andy Prowl Jan 07 '13 at 17:12
  • @Andy: I never claimed that you claimed it! It's merely part of the reason why it would be near-pointless to implement this functionality. My answer is not designed as a response to any of _your_ specific claims... – Lightness Races in Orbit Jan 07 '13 at 17:13
  • @LightnessRacesinOrbit: My point is just that 1) there's no reason why implicitly generated closures could not have defaults in their signature; 2) there's no need to have the defaults visible at any call site (i.e. outside of the scope where lambdas are defined), that's just not what is asked for - and btw yes, *that* would require changing the type system. Whether 1) and 2) would make lambdas with defaults of little or big use does not answer the question "why are default arguments *prohibited*?". The right answer IMO is "for no reason, they just didn't think about it". – Andy Prowl Jan 07 '13 at 17:22
  • @Andy: (1) Because defaults _are never_ in a signature (actually during this discussion I've discovered that they _are_, but they're _not_ in the function _type_). They just aren't. Without fundamentally changing function types, you simply can't do this. Ever. At all. (2) Sure, if the defaults were part of the lambda's function type then this wouldn't matter so much. As it stands today, it does. So the answer is "for these reasons it would be more difficult than is worth it". I'm sure they _thought_ about it. Like, really briefly! – Lightness Races in Orbit Jan 07 '13 at 17:28
  • @LightnessRacesinOrbit: I disagree, but I am wondering whether it is not the case to move this discussion to the chat. Or just to let it be, if you have no time for it. – Andy Prowl Jan 07 '13 at 17:30
  • @AndyProwl: I'm just not sure that I have anything left to add! We're kinda going in circles I think. – Lightness Races in Orbit Jan 07 '13 at 17:31
  • @LightnessRacesinOrbit: I know, because you keep repeating the same arguement and (i believe unintentionally) ignoring mine. you probably have the same feeling, that's why i'd like to clarify on chat. but we don't need to – Andy Prowl Jan 07 '13 at 17:32
  • @Andy: I've been responding directly to each of your points. Maybe we can come back to it another day – Lightness Races in Orbit Jan 07 '13 at 17:37
  • @LightnessRacesInOrbit: no, you haven't. I'll write my last comment and stop bothering you. If you define a functor of your own, whatever it is, with a call operator, that call operator *can* have defaults. And you *can* create an instance of your own functor and invoke its call operator omitting the default arguments. So there is no reason why a functor which is generated *automatically* from a lambda could not be generated with defaults on its call operator. No need to mention at all the definition of what is conceptually part of a type or a signature and what is not. Cheers. – Andy Prowl Jan 07 '13 at 17:40
  • @Andy: The functor could exist with defaults, yes. Hmm I suppose with `auto` "resolving" to the functor type itself then this could work. Is that what you mean? I contend that using a lambda locally with its functor type is highly rare -- we usually invoke them through function pointers or a generic alternative such as `std::function`, with which I still can't see how we'd be able to make use of the defaults. So we'd need a type system change for defaults on lambdas to be useful in the predominant use case. Are we closer now? – Lightness Races in Orbit Jan 07 '13 at 17:43
  • My two cents: There is no technical reason defaults couldn't be allowed. But they would only be useable through `auto` or templates, not through a function pointer or `std::function`, which would make the feature less useful. The type of a lambda is an unnamed `struct`/`class`, not a function type. That `struct` could hypothetically have a member `operator()` function with a default argument. – aschepler Jan 07 '13 at 18:17
  • @LightnessRacesinOrbit: yes, we are closer. My view is exactly the same as the one expressed by aschepler above (two cents well spent IMO). I don't want to discuss whether using a lambda locally with its functor type is common, uncommon, rare, or highly rare. I just want to answer the question: "why is it *forbidden*?". And since there is no technical reason, no complication, and a very trivial way to achieve it, my answer is just "they didn't think about it". – Andy Prowl Jan 07 '13 at 19:20
  • OK, i must correct myself: 5.1.2/4 explicitly states "Default arguments (8.3.6) shall not be specified in the parameter-declaration-clause of a lambdadeclarator". So they must have thought about it. Which turns my answer into a "no idea". – Andy Prowl Jan 07 '13 at 19:23
  • Exactly, which is in turn what I've been trying to say since the beginning. Really, to me implementing defaults in lambdas looks so natural, trivial, and safe that it takes a good reason *not* to support it, rather than a good reason *why* it should be supported. That's what the standard (and anybody else to be honest) has been mute about. – Andy Prowl Jan 07 '13 at 19:54
5

I agree that there is no real "technical" restriction per se to allowing default arguments in lambdas to work in some cases. It wouldn't mangle your pointers and auto, because the type of a function is not affected by default arguments. But that's also why this wouldn't be terribly practical.

Why?

Because default arguments, while part of a function signature, are not part of a function type:

[C++11: 1.3.17]:
signature
<function> name, parameter type list (8.3.5), and enclosing namespace (if any)
[ Note: Signatures are used as a basis for name mangling and linking. —end note ]

[C++11: 8.3.5/6]: [..] The return type, the parameter-type-list, the ref-qualifier, and the cv-qualifier-seq, but not the default arguments (8.3.6) or the exception specification (15.4), are part of the function type. [ Note: Function types are checked during the assignments and initializations of pointers to functions, references to functions, and pointers to member functions. —end note ]

They are essentially a piece of syntactic sugar that are "activated" by the compiler being able to see the declaration of the function you use, and injected at the point of the function call:

#include <iostream>

void foo(int x = 5)
{
   std::cout << x << '\n';
}

int main()
{
   foo();
}
  • Output: 5

The default argument is "visible".

However, when you "hide" your function behind a pointer:

int main()
{
    void (*bar)(int) = &foo;
    bar();
}
  • Error: too few arguments to function

The type of bar is correct, and the compiler knows that foo has a default, but there's simply no direct syntax that exists to inform the compiler at the point of calling bar that bar is also foo. Sure, in this trivial scenario it could figure it out by observing the assignment, but that's hardly justification for the wider argument.

For the same reason, default arguments stated only in a definition not visible at the call site are next to useless:

// a.h
void foo(int);

// a.cpp
#include "a.h"
#include <iostream>

void foo(int x = 5)
{
   std::cout << x << '\n';
}

// main.cpp
#include "a.h"

int main()
{
    foo();
}
  • Error in main.cpp: too few arguments to function

I imagine that this is the reason for:

[C++11: 8.3.6/4]: [..] Declarations in different scopes have completely distinct sets of default arguments. [..]

We are allowed to "pile up" default arguments for class non-template member function definitions ([C++11 8.3.6/6]); the example indicates that this default will still only apply in the same TU, which follows the behaviour we've seen above in my second code snippet.

So, if default arguments are not part of the function type, and must be unambiguously visible to the call site, then there are only a handful of trivially contrived corner-cases in which they would be useful for lambdas, which is when they are called in the same scope that they are created so the compiler can tractibly figure out how to "fill in" the default argument for the call to the lambda and, well, what is the point of that? Not a lot, I tell thee.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Just a thought. One could consider that with `void (*bar)(int) = &foo;` that `bar` as defined would require it to be called with a single `int` parameter, thus making the call `bar();` illegal. Further, `void (*bar2)() = &foo;` could generate an intermediate function that would automatically add the default argument for you. That would make your statement *"but there's simply no direct syntax that exists to inform the compiler at the point of calling `bar` that bar is also `foo`."* incorrect, as there would be a direct syntax available. – Adrian Oct 30 '21 at 18:46
  • Also, lambdas are simplified functors, and you can have default arguments in those. A type is concrete, but the default arguments are not. It's not till you call or query a function with default arguments, that it need give up an actual function type. – Adrian Oct 30 '21 at 18:52
3

As the comments to the question suggest, there's probably no technical reason for there to be no default arguments. But the flip question is "Is there a practical reason for default arguments?" I would think the answer to this is "no", and here's why.

In order to call a lambda, one thing you can do is call it right away

[] { printf("foo"); }();

I'm sure this has limited uses, if any, so let's move on. The only other way to call a lambda is to bind it to a variable first, and there's a few options here.

  1. Use auto. So we get auto foo = [] { printf("foo"); }; foo();
  2. Bind it to a function pointer: void (*foo)() = [] { printf("foo"); }; foo(). Of course, this only works if the lambda doesn't capture.
  3. Do the equivalent of either 1 or 2 by passing the lambda to a function or function template.

Now let's go through the usefulness of default arguments in each case

  1. We're calling the lambda directly in this case, so the code is probably tight-knit enough that we won't be calling the lambda with various numbers of arguments. If we are, the lambda could (should?) probably be refactored into a more general component. I don't see any practical benefit here.
  2. (see 1)
  3. We pass the lambda off to another function. I don't see the practical benefit to a default argument here, either. Think back to good old functors (which can have default arguments) - I can't say I know of too many functions which count on default arguments being present even for these. Since lambdas are effectively just functors, there's no reason for this observation to change suddenly.

I think these points are enough to say the default arguments to a lambda really aren't that useful. Also, I see some people are talking about issues with the type of a lambda if it had default arguments, but this is a non-issue IMO. You can always write up your own functor that does the same thing, and which does have the default argument. Also, about degrading to a function pointer, there's not much to say either. Take a normal function

void func(int i = 0)
{
}

and take it's address. What do you get? A void (*)(int). There's no reason a lambda would follow different rules.

Ken Wayne VanderLinde
  • 18,915
  • 3
  • 47
  • 72
0

I've read some of these responses, and everyone (from what I read tl;dr) was referring to restrictions in the type system. This really doesn't have anything to do with that. Although a function's type includes all parameters, default or not, a functor with default arguments can be thought of as a fuzzy function, who's type doesn't come into being until you look at it.

As a lambda is syntactic sugar to simplify a functor's use, with some cool type deduction thrown in. It is, when boiled down and converted by the compiler, a functor when it has captures (a function if it does not). So there is really no reason why you can't have it in a lambda. Observe:

#include<functional>
#include<iostream>

int main()
{
    // my lambda as written as a functor.  Not pretty eh?  But it works. o.O
    struct {
    void operator()(char const* x = "default") {
         std::cout << x << std::endl;
    } } fn;

    fn("Hi");
    fn();
    std::function<void(char const*)> fn_copy_1 = fn;
    std::function<void()>            fn_copy_0 = fn;
    fn_copy_1("there");
    fn_copy_0();
    return 0;
}

Results (running example here):

Hi
default
there
default

All without any changes to the type system.

So, why is there such a restriction? My guess, nobody thought it would be useful and it would be less stuff to test if it wasn't implemented. Things are added to the language by the users calling out that they need feature X. If no one asks for it and there isn't enough value associated with it, then it's not added. This is not to say it can't be added in the future, but only if there is call for it.

Adrian
  • 10,246
  • 4
  • 44
  • 110
  • You can also have `auto fn_copy_1 = [&](char const* x){fn(x);}; auto fn_copy_0 = [&](){fn("default");};` which creates a lambda function with default parameters. Just need another lambda function for each default parameter. – QuentinUK Jan 05 '22 at 19:17
  • @QuentinUK, yes, but that isn't an lambda's with a default argument, that is having two differently named lambdas calling a first one, meaning you would have to call the differently named lambda to have the default that you wanted. However, if you want to have the same named lambda had a default, you could do what you are suggesting plus what is shown in [Overload a lambda function](http://stackoverflow.com/a/58700664/1366368) to overload the lambda name such that it is in effect allowing a default argument. So again, this could be implemented, it just isn't. – Adrian Jan 07 '22 at 05:08
  • Although I did know about lambda overloading at the time I wrote the original answer, I chose not to include it because I felt that it didn't really add anything to the argument, it is just another way to show that there is no real reason why lambda default parameters is disallowed other than it prolly makes it easier to implement the compiler. – Adrian Jan 07 '22 at 05:11