Hacker News new | ask | show | jobs
by marvy 2115 days ago
The title is slightly click-bait-y: C++20 doesn't have default parameters. It talks about how to fake it with structs.

It's a pretty convincing fake, but it has one problem: the person who wrote the function needs to have written it that way. What I wish more languages had (C++, Java, etc.) is the following:

Suppose I write some function that take way too many parameters:

void foo(char a, short b, long c, float d, double e){}

What I want, as a caller, is for the language to let me get a struct corresponding to the argument list, something like this:

    foo::args whatever;
    whatever.e = 3.14;
    // fill in the rest
And then add a bit of magic syntax so we can "unpack" that struct to actually call foo. (Extending this proposal to handle varargs is left as an exercise to the reader, because I have no idea.)
4 comments

That's quite interesting.

I see two possible implementations:

- either the struct is replicated at the function call (not really efficient, but the semantics are straightforward);

- either the struct is used to prepare directly the stack for the function call (more efficient, but the semantics must be defined).

One of the issues of the second approach is that if the structure/variable is a classical one, what should happen if we use the variable after the call?

If we have to read the values inserted before the call then we have to keep a copy of the structure in the stack (so it's the same as the first approach). Or we can consider that the variable no longer exists in the scope. Which corresponds to the ownership concept in Rust for example. (but, to my knowledge, this does not exist in C++)

What is the best option? Or are there other options?

Another question, what sizeof(foo::args) should return ?

I think foo::args should be a normal struct type, so sizeof(foo::args) would follow the usual rules, just as if someone had manually written

struct foo_args{char a; short b; long c; float d; etc...}

and then asked for sizeof(foo_args).

I have thought about it a little more, and I think it's the right solution as well.

From the first proposal the compiler can directly prepare the stack for the call.

As in this example: https://godbolt.org/z/f17szP

How about `std::make_from_tuple` for constructors or `std::apply` for functions (C++17)?

It might be a bit verbose, but I think I would still prefer this over native syntax for unpacking.

Why would you kill your compile times like that.
This mostly solves the unpacking problem. Thus, there are only two problems left:

1. I need to handcraft the tuple type myself, and make sure it matches the function declaration. (In other words, I don't want to manually write tuple<char, short>. I want to write foo::arg_tuple.)

2. This provides no support for named parameters. Tuples in C++ are numbered, not named.

Though limited, C++ does support default parameters: https://en.cppreference.com/w/cpp/language/default_arguments.
sorry, I meant named parameters
Ahh this is very, very cool.

In general, it'd be really nice to have compile-time access to compile-time function info like this. Arguments, their types, etc.

This is commonly called `function_traits`--for example: https://www.boost.org/doc/libs/1_43_0/libs/type_traits/doc/h...