[BUG] Cannot value initialise a function argument with equivalent of C++ `{}`
bluetarpmedia opened this issue · comments
Describe the bug
I can't find a Cpp2 syntax to value initialise an argument passed to a function using its default constructor.
To Reproduce
Run cppfront on this code:
log: (message: std::string_view,
context: std::string,
event_id: int) =
{
std::println("{} {} {}", message, context, event_id);
}
main: () = {
log("event", (), 123); // (1) Error in C++ compiler
log("event", _, 123); // (2) Error in C++ compiler
log("event", {}, 123); // (3) Error in cppfront
}
(1) produces this error:
main.cpp2:10:19: error: expected expression
10 | log("event", (), 123);
| ^
(2) produces this error:
main.cpp2:10:18: error: use of undeclared identifier '_'
10 | log("event", _, 123);
| ^
(3) produces a cppfront syntax error.
Repro on Godbolt
Additional context
I was translating the ranges::find_end
example from cppreference and have used explicit arguments like this:
found4:= std::ranges::find_end(
secret, "SWORD"sv,
std::ranges::equal_to(),
std::identity(),
:(c: char) std::tolower(c));
instead of the original:
const auto found4 = std::ranges::find_end(secret, "SWORD"sv,
{},
{},
[](char c) { return std::tolower(c); });
Hi Neil,
The solution I think might be simplest for this is to use '{}' for default initialized arguments just like c++, and adding it would be pretty straight forward. One approach is to allow brace expressions here:
Lines 5715 to 5718 in 130f149
However that approach might not be best one given the comment right above it. I can probably add logic to the parser to grab '{}' only in this specific instance, but I'd like to hear from our BDFL, @hsutter, before going down any route.
Thanks.
Thanks! In Cpp2 so far, {
}
are used only for scopes.
Hot take: ()
does already mean default construction (e.g., x : int = ();
) so an empty list argument ()
could be lowered to {}
.
I like that idea, I'll try it out.
if ()
is changed to lower to {}
then wouldn't that imply that explicit
constructors should be included in the overload set? i.e.
The following doesn't work in C++ (but should)
struct B {
explicit B(int);
};
void foo(B);
B asdf() {
B _ = auto{1}; // should mean B _ = B{1};
foo({1}); // should mean foo(B{1}); (some might disagree)
foo(auto{1}); // should mean foo(B{1});
if (rand())
return {1}; // should mean return B{1}; (some might disagree)
else
return auto{1}; // should mean return B{1};
}
The following should work in Cpp2:
B: type = {
operator=: (out this, _: i32) = {} // explicit ctor
}
foo: (_: B) = {}
B asdf() {
_: B = (1);
foo((1)); // some might disagree that this should work
foo(:_ = (1));
foo(_(1));
if (rand())
return (1); // some might disagree that this should work
else if (rand())
return :_ = (1);
else
return _(1);
}