Skip to content

Commit fd2dab7

Browse files
committed
feat: allow template specialization
The syntax is `specialize<specialization_arguments>` after the optional template parameter list. Some examples from the tests: ```Cpp2 std: namespace = { common_type: @struct @print specialize<outer, outer> type = { type: type == outer; } } v: <T> const i32 = 1; v: <> specialize<void> const i32 = 2; v: specialize<i64> const i32 = 3; v: <T> specialize<* T> std::optional<int> == 6; ```
1 parent ccf7011 commit fd2dab7

22 files changed

+357
-31
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a1: <T> namespace == { }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a2: namespace requires true == { }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a3: type requires true = { }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a4: specialize<> type == int;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a5: specialize<> namespace == std;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
n1: <T> namespace = { }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
n2: namespace requires true = { }

regression-tests/pure2-print.cpp2

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ outer: @print type = {
104104

105105
}
106106

107+
std: namespace = {
108+
common_type: @struct @print specialize<outer, outer> type = {
109+
type: type == outer;
110+
}
111+
numbers: namespace = {
112+
pi_v: /*@print*/ specialize<outer> const double = pi_v<double>;
113+
}
114+
}
115+
107116
main: () = {
108117
outer::test();
109118
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
t: @cpp1_rule_of_zero <T> type = {
2+
public a: i32 = 1;
3+
}
4+
t: @cpp1_rule_of_zero <T> specialize<T> type requires std::is_void_v<T> = {
5+
public b: i32 = 2;
6+
}
7+
t: @cpp1_rule_of_zero specialize<i64> type = {
8+
public c: i32 = 3;
9+
}
10+
t: @cpp1_rule_of_zero specialize<* i8> type = {
11+
public f: () = 17;
12+
public v: int == 29;
13+
}
14+
t: @cpp1_rule_of_zero <T> specialize<* T> type = {
15+
public v: int == 17;
16+
public f: () = 29;
17+
}
18+
u: @cpp1_rule_of_zero <T...> type = {
19+
public a: i32 = 1;
20+
}
21+
u: @cpp1_rule_of_zero specialize<> type = {
22+
public a: i32 = 2;
23+
}
24+
u: specialize<i16> type = { }
25+
v: <T> const i32 = 1;
26+
v: <> specialize<void> const i32 = 2;
27+
v: specialize<i64> const i32 = 3;
28+
v: specialize<i16> std::optional<i32> == 4;
29+
v: <> specialize<i8> std::optional<i8> == 5;
30+
v: <T> specialize<* T> std::optional<int> == 6;
31+
main: () = {
32+
assert(t<i32>().a == 1);
33+
assert(t<void>().b == 2);
34+
assert(t<i64>().c == 3);
35+
assert(t<* i8>::f() == 17);
36+
assert(t<* i8>::v == 29);
37+
assert(t<* i16>::v == 17);
38+
assert(t<* i16>::f() == 29);
39+
assert(u<i32>().a == 1);
40+
assert(u<>().a == 1);
41+
assert(v<i32> == 1);
42+
assert(v<void> == 2);
43+
assert(v<i64> == 3);
44+
static_assert(v<i16> == 4);
45+
static_assert(v<i8> == 5);
46+
static_assert(v<* int> == 6);
47+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pure2-alias-1-error.cpp2...
2+
pure2-alias-1-error.cpp2(1,19): error: a namespace or namespace alias cannot have template parameters
3+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pure2-alias-2-error.cpp2...
2+
pure2-alias-2-error.cpp2(1,15): error: 'requires' is not allowed on a namespace alias (at 'requires')
3+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pure2-alias-3-error.cpp2...
2+
pure2-alias-3-error.cpp2(1,10): error: 'requires' is not allowed on a type alias that does not have a template parameter list (at 'requires')
3+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pure2-alias-4-error.cpp2...
2+
pure2-alias-4-error.cpp2(1,18): error: a type alias cannot be specialized
3+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pure2-alias-5-error.cpp2...
2+
pure2-alias-5-error.cpp2(1,18): error: a namespace alias cannot be specialized
3+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pure2-namespace-1-error.cpp2...
2+
pure2-namespace-1-error.cpp2(1,19): error: a namespace or namespace alias cannot have template parameters
3+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pure2-namespace-2-error.cpp2...
2+
pure2-namespace-2-error.cpp2(1,15): error: 'requires' is not allowed on a namespace alias (at 'requires')
3+

regression-tests/test-results/pure2-print.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@
1111
#line 6 "pure2-print.cpp2"
1212
class outer;
1313

14+
#line 107 "pure2-print.cpp2"
15+
namespace std {
16+
17+
#line 111 "pure2-print.cpp2"
18+
namespace numbers {
19+
20+
}
21+
}
22+
1423

1524
//=== Cpp2 type definitions and function declarations ===========================
1625

@@ -81,6 +90,15 @@ CPP2_REQUIRES_ (cpp2::impl::cmp_greater_eq(sizeof...(Args),0u)) ;
8190
#line 105 "pure2-print.cpp2"
8291
};
8392

93+
namespace std {
94+
template<> class common_type<outer,outer> {
95+
public: using type = outer;
96+
};
97+
namespace numbers {
98+
/*@print*/
99+
}
100+
}
101+
84102
auto main() -> int;
85103

86104
//=== Cpp2 function definitions =================================================
@@ -206,6 +224,15 @@ requires (cpp2::impl::cmp_greater_eq(sizeof...(Args),0u)) {
206224
auto outer::y([[maybe_unused]] cpp2::impl::in<CPP2_TYPEOF(0)> unnamed_param_1) -> void{}
207225

208226
#line 107 "pure2-print.cpp2"
227+
namespace std {
228+
229+
#line 111 "pure2-print.cpp2"
230+
namespace numbers {
231+
template<> double const pi_v<outer> {pi_v<double>};
232+
}
233+
}
234+
235+
#line 116 "pure2-print.cpp2"
209236
auto main() -> int{
210237
outer::test();
211238
}

regression-tests/test-results/pure2-print.cpp2.output

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,11 @@ outer:/* @print */ type =
151151
{
152152
}
153153
}
154+
155+
156+
common_type:/* @struct @print */ specialize<outer, outer> type =
157+
{
158+
public type: type == outer;
159+
}
154160
ok (all Cpp2, passes safety checks)
155161

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
2+
#define CPP2_IMPORT_STD Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
#line 1 "pure2-template-specialization.cpp2"
10+
template<typename T> class t;
11+
#line 2 "pure2-template-specialization.cpp2"
12+
13+
14+
#line 18 "pure2-template-specialization.cpp2"
15+
template<typename ...T> class u;
16+
17+
18+
//=== Cpp2 type definitions and function declarations ===========================
19+
20+
#line 1 "pure2-template-specialization.cpp2"
21+
template<typename T> class t {
22+
#line 2 "pure2-template-specialization.cpp2"
23+
public: cpp2::i32 a {1};
24+
};
25+
template<typename T> requires( std::is_void_v<T> )
26+
class t<T> {public: cpp2::i32 b {2};
27+
};
28+
template<> class t<cpp2::i64> {
29+
public: cpp2::i32 c {3};
30+
};
31+
template<> class t<cpp2::i8*> {
32+
public: [[nodiscard]] static auto f() -> decltype(auto);
33+
public: static const int v;
34+
};
35+
template<typename T> class t<T*> {
36+
public: static const int v;
37+
public: [[nodiscard]] static auto f() -> decltype(auto);
38+
};
39+
template<typename ...T> class u {
40+
public: cpp2::i32 a {1};
41+
};
42+
template<> class u<> {
43+
public: cpp2::i32 a {2};
44+
};
45+
template<> class u<cpp2::i16> {
46+
public: u() = default;
47+
public: u(u const&) = delete; /* No 'that' constructor, suppress copy */
48+
public: auto operator=(u const&) -> void = delete;
49+
};
50+
#line 25 "pure2-template-specialization.cpp2"
51+
template<typename T> extern cpp2::i32 const v;
52+
53+
#line 28 "pure2-template-specialization.cpp2"
54+
template<> std::optional<cpp2::i32> inline constexpr v<cpp2::i16>{ 4 };
55+
template<> std::optional<cpp2::i8> inline constexpr v<cpp2::i8>{ 5 };
56+
template<typename T> std::optional<int> inline constexpr v<T*>{ 6 };
57+
auto main() -> int;
58+
59+
//=== Cpp2 function definitions =================================================
60+
61+
#line 1 "pure2-template-specialization.cpp2"
62+
63+
#line 11 "pure2-template-specialization.cpp2"
64+
[[nodiscard]] auto t<cpp2::i8*>::f() -> decltype(auto) { return 17; }
65+
inline CPP2_CONSTEXPR int t<cpp2::i8*>::v{ 29 };
66+
67+
#line 15 "pure2-template-specialization.cpp2"
68+
template <typename T> inline CPP2_CONSTEXPR int t<T*>::v{ 17 };
69+
template <typename T> [[nodiscard]] auto t<T*>::f() -> decltype(auto) { return 29; }
70+
71+
#line 25 "pure2-template-specialization.cpp2"
72+
template<typename T> cpp2::i32 const v {1};
73+
template<> cpp2::i32 const v<void> {2};
74+
template<> cpp2::i32 const v<cpp2::i64> {3};
75+
76+
#line 31 "pure2-template-specialization.cpp2"
77+
auto main() -> int{
78+
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i32>().a == 1) ) { cpp2::cpp2_default.report_violation(""); }
79+
if (cpp2::cpp2_default.is_active() && !(t<void>().b == 2) ) { cpp2::cpp2_default.report_violation(""); }
80+
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i64>().c == 3) ) { cpp2::cpp2_default.report_violation(""); }
81+
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i8*>::f() == 17) ) { cpp2::cpp2_default.report_violation(""); }
82+
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i8*>::v == 29) ) { cpp2::cpp2_default.report_violation(""); }
83+
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i16*>::v == 17) ) { cpp2::cpp2_default.report_violation(""); }
84+
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i16*>::f() == 29) ) { cpp2::cpp2_default.report_violation(""); }
85+
if (cpp2::cpp2_default.is_active() && !(u<cpp2::i32>().a == 1) ) { cpp2::cpp2_default.report_violation(""); }
86+
if (cpp2::cpp2_default.is_active() && !(u<>().a == 1) ) { cpp2::cpp2_default.report_violation(""); }
87+
if (cpp2::cpp2_default.is_active() && !(v<cpp2::i32> == 1) ) { cpp2::cpp2_default.report_violation(""); }
88+
if (cpp2::cpp2_default.is_active() && !(v<void> == 2) ) { cpp2::cpp2_default.report_violation(""); }
89+
if (cpp2::cpp2_default.is_active() && !(v<cpp2::i64> == 3) ) { cpp2::cpp2_default.report_violation(""); }
90+
static_assert(v<cpp2::i16> == 4);
91+
static_assert(v<cpp2::i8> == 5);
92+
static_assert(v<int*> == 6);
93+
}
94+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-template-specialization.cpp2... ok (all Cpp2, passes safety checks)
2+

0 commit comments

Comments
 (0)