But we already have function overloading, which gives you the same thing with a much simpler syntax.
Your example code could be (in C++98 and later)

Ok, I should have clarified that point. The issue with this is the programmer has to copy / paste and then maintain two different functions. It just so happened with the example I was working with this is less convenient than having the different behavior internal to a single function rather than maintained externally via overloading and calling two different functions. Of course, overloading is a perfectly valid solution, just more work in this case. It often will not always be this way.

Notice that in your specific case, `mode` has only two meaningful values "1" and "not 1" and so it should probably be a `bool`, not an `int`.

Ok, it's just the case for the limited small example I copied here, this isn't the complete function, the actual thing is a couple of hundred lines.

> Even better for your rapid-prototyping work:

    int draw(int param);
    int draw_with_mode(int param, int mode);

    draw_with_mode(1, -1);

This is a good point, but consider the case of more than just a single optional argument. For M optional arguments, the number of function calls goes like 2^M... probably... I haven't given it much thought. Or is it factorial(M). Probably the latter.

Best Regards


From: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Sent: Sunday, July 19, 2020 16:34
To: Std-Proposals <std-proposals@lists.isocpp.org>
Cc: Ed Bird <HYPER-NOVA@live.co.uk>
Subject: Re: [std-proposals] Proposal: template function solution to Pythonic optional function arguments
 
On Sun, Jul 19, 2020 at 11:45 AM Ed Bird via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Hi,

I am not sure if this is the correct email address to which I should direct this enquiry

It is (I mean I don't know a better place, except for /r/cpp or the Cpplang Slack or I think there's a Discord now).

[...] In my view, if a function has an optional argument, then it should be treated similarly to how template classes are treated. In other words, this is an example of a case where one block of code should produce multiple blocks of executable code when compiled.

But we already have function overloading, which gives you the same thing with a much simpler syntax.
Your example code could be (in C++98 and later)

void draw(int parameter) {
    do_draw(parameter);
}
void draw(int parameter, int mode) {
    do_draw(mode == 1 ? -1 : parameter);
}

We also have default function arguments, although I recommend against their use:

void draw(int parameter, int mode = 42) {
    do_draw(mode == 1 ? -1 : parameter);
}

Notice that in your specific case, `mode` has only two meaningful values "1" and "not 1" and so it should probably be a `bool`, not an `int`.

I don't personally like the syntax of using `#if` to achieve the anticipated result, but this is just my personal opinion

Indeed, you can't use preprocessor macros for this, because the C preprocessor doesn't know anything about functions or variables or anything like that. That's also why C++ templates use the dedicated `template` keyword, instead of some weird code-duplicating macro magic.

I actually introduced a bug due to the fact that I had a long list of default parameters, and missed one when calling the function. An implicit cast from int to bool was responsible for the function behaving differently to how I expected. I fixed this by putting in the missing arguments, of course.

Indeed. Default function arguments are the devil.
 
But it wouldn't have happened if I could have done `draw(1, mode=-1);`

Even better for your rapid-prototyping work:

    int draw(int param);
    int draw_with_mode(int param, int mode);

    draw_with_mode(1, -1);

with no default function arguments at all. This way you can't accidentally forget the mode; if you try to call `draw_with_mode(1)` you get a compiler error.
Of course I can't stop you from spelling it `draw2` instead of `draw_with_mode`. ;)

HTH,
Arthur