Skip to content

Commit 873b760

Browse files
committed
Allow function parameter default arguments
Closes #1189 I had been experimenting with not allowing default arguments for function parameters, in part because of the potential for creating order-dependent code; the way to find out whether they're necessary is to not support them and see if that leaves a usability hole. The result of the experiment is that it does leave a hole: There's persistent feedback that default arguments are often useful, and are actually necessary for a few cases including particularly `std::source_location` parameters. As for order independence, there are already ways to opt into creating potentially order-dependent code (such as by deduced return types which depend on function bodies). So I think it's time to enable default arguments, and Cpp2 is still order-independent by default. This example now works: my_function_name: ( fn: *const char = std::source_location::current().function_name() ) = { std::cout << "calling: (fn)$\n"; } main: (args) = { my_function_name(); } // On MSVC 2022, prints: // calling: int __cdecl main(const int,char **) // On GCC 14, prints: // calling: int main(int, char**)
1 parent 658d307 commit 873b760

12 files changed

+172
-16
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
// Note: Using source_location requires GCC 11 or higher,
3+
// Clang 16 or higher, MSVC 2019 16.10 or higher.
4+
// Older compilers will emit failures for this test case.
5+
my_function_name: (
6+
fn: *const char = std::source_location::current().function_name()
7+
)
8+
= {
9+
std::cout << "calling: (fn)$\n";
10+
}
11+
12+
f: (x: i32 = 0) = { std::cout << x; }
13+
14+
main: (args) = {
15+
my_function_name();
16+
f();
17+
f(1);
18+
f(2);
19+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pure2-default-arguments.cpp2:6:61: error: no member named 'source_location' in namespace 'std'
2+
char const* fn = CPP2_UFCS_NONLOCAL(function_name)(std::source_location::current())
3+
~~~~~^
4+
1 error generated.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
In file included from pure2-default-arguments.cpp:7:
2+
../../../include/cpp2util.h:2086:28: error: local variable ‘obj’ may not appear in this context
3+
2086 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<17>(x); }
4+
| ^~~
5+
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
6+
2047 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
7+
| ^~~~~~~~~~~
8+
../../../include/cpp2util.h:2086:15: note: in expansion of macro ‘CPP2_FORWARD’
9+
2086 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<17>(x); }
10+
| ^~~~~~~~~~~~
11+
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
12+
2107 | { return !x.has_value(); }
13+
| ^~~~~~~~~
14+
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
15+
2137 | { return std::any_cast<T>( x ); }
16+
| ^
17+
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
18+
../../../include/cpp2util.h:2086:92: error: local variable ‘params’ may not appear in this context
19+
2086 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<17>(x); }
20+
| ^~~~~~
21+
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
22+
2047 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
23+
| ^~~~~~~~~~~
24+
../../../include/cpp2util.h:2086:79: note: in expansion of macro ‘CPP2_FORWARD’
25+
2086 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<17>(x); }
26+
| ^~~~~~~~~~~~
27+
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
28+
2107 | { return !x.has_value(); }
29+
| ^~~~~~~~~
30+
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
31+
2137 | { return std::any_cast<T>( x ); }
32+
| ^
33+
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
34+
../../../include/cpp2util.h:2087:74: error: local variable ‘obj’ may not appear in this context
35+
2087 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<18>(x); }
36+
| ^~~
37+
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
38+
2047 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
39+
| ^~~~~~~~~~~
40+
../../../include/cpp2util.h:2087:61: note: in expansion of macro ‘CPP2_FORWARD’
41+
2087 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<18>(x); }
42+
| ^~~~~~~~~~~~
43+
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
44+
2107 | { return !x.has_value(); }
45+
| ^~~~~~~~~
46+
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
47+
2137 | { return std::any_cast<T>( x ); }
48+
| ^
49+
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
50+
../../../include/cpp2util.h:2087:93: error: local variable ‘params’ may not appear in this context
51+
2087 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<18>(x); }
52+
| ^~~~~~
53+
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
54+
2047 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
55+
| ^~~~~~~~~~~
56+
../../../include/cpp2util.h:2087:80: note: in expansion of macro ‘CPP2_FORWARD’
57+
2087 | if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<18>(x); }
58+
| ^~~~~~~~~~~~
59+
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
60+
2107 | { return !x.has_value(); }
61+
| ^~~~~~~~~
62+
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
63+
2137 | { return std::any_cast<T>( x ); }
64+
| ^
65+
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
66+
pure2-default-arguments.cpp2:6:61: error: ‘std::source_location’ has not been declared
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
calling: int main(int, char**)
2+
012
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
calling: int __cdecl main(const int,char **)
2+
012
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pure2-default-arguments.cpp
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
2+
#define CPP2_IMPORT_STD Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
#line 1 "pure2-default-arguments.cpp2"
10+
11+
12+
//=== Cpp2 type definitions and function declarations ===========================
13+
14+
#line 1 "pure2-default-arguments.cpp2"
15+
16+
// Note: Using source_location requires GCC 11 or higher,
17+
// Clang 16 or higher, MSVC 2019 16.10 or higher.
18+
// Older compilers will emit failures for this test case.
19+
#line 5 "pure2-default-arguments.cpp2"
20+
auto my_function_name(
21+
char const* fn = CPP2_UFCS_NONLOCAL(function_name)(std::source_location::current())
22+
) -> void;
23+
24+
#line 12 "pure2-default-arguments.cpp2"
25+
auto f(cpp2::impl::in<cpp2::i32> x = 0) -> void;
26+
27+
auto main(int const argc_, char** argv_) -> int;
28+
29+
//=== Cpp2 function definitions =================================================
30+
31+
#line 1 "pure2-default-arguments.cpp2"
32+
33+
#line 5 "pure2-default-arguments.cpp2"
34+
auto my_function_name(
35+
char const* fn
36+
) -> void
37+
{
38+
std::cout << "calling: " + cpp2::to_string(fn) + "\n";
39+
}
40+
41+
#line 12 "pure2-default-arguments.cpp2"
42+
auto f(cpp2::impl::in<cpp2::i32> x) -> void{std::cout << x; }
43+
44+
#line 14 "pure2-default-arguments.cpp2"
45+
auto main(int const argc_, char** argv_) -> int{
46+
auto const args = cpp2::make_args(argc_, argv_);
47+
#line 15 "pure2-default-arguments.cpp2"
48+
my_function_name();
49+
f();
50+
f(1);
51+
f(2);
52+
}
53+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-default-arguments.cpp2... ok (all Cpp2, passes safety checks)
2+

regression-tests/test-results/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
cppfront compiler v0.7.2 Build 9804:1033
2+
cppfront compiler v0.7.2 Build 9809:1046
33
Copyright(c) Herb Sutter All rights reserved
44

55
SPDX-License-Identifier: CC-BY-NC-ND-4.0

source/build.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"9804:1033"
1+
"9809:1046"

0 commit comments

Comments
 (0)