Skip to content

Commit

Permalink
feat: allow template specialization
Browse files Browse the repository at this point in the history
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;
```
  • Loading branch information
JohelEGP committed Oct 9, 2024
1 parent ccf7011 commit fd2dab7
Show file tree
Hide file tree
Showing 22 changed files with 357 additions and 31 deletions.
1 change: 1 addition & 0 deletions regression-tests/pure2-alias-1-error.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a1: <T> namespace == { }
1 change: 1 addition & 0 deletions regression-tests/pure2-alias-2-error.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a2: namespace requires true == { }
1 change: 1 addition & 0 deletions regression-tests/pure2-alias-3-error.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a3: type requires true = { }
1 change: 1 addition & 0 deletions regression-tests/pure2-alias-4-error.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a4: specialize<> type == int;
1 change: 1 addition & 0 deletions regression-tests/pure2-alias-5-error.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a5: specialize<> namespace == std;
1 change: 1 addition & 0 deletions regression-tests/pure2-namespace-1-error.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
n1: <T> namespace = { }
1 change: 1 addition & 0 deletions regression-tests/pure2-namespace-2-error.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
n2: namespace requires true = { }
9 changes: 9 additions & 0 deletions regression-tests/pure2-print.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ outer: @print type = {

}

std: namespace = {
common_type: @struct @print specialize<outer, outer> type = {
type: type == outer;
}
numbers: namespace = {
pi_v: /*@print*/ specialize<outer> const double = pi_v<double>;
}
}

main: () = {
outer::test();
}
47 changes: 47 additions & 0 deletions regression-tests/pure2-template-specialization.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
t: @cpp1_rule_of_zero <T> type = {
public a: i32 = 1;
}
t: @cpp1_rule_of_zero <T> specialize<T> type requires std::is_void_v<T> = {
public b: i32 = 2;
}
t: @cpp1_rule_of_zero specialize<i64> type = {
public c: i32 = 3;
}
t: @cpp1_rule_of_zero specialize<* i8> type = {
public f: () = 17;
public v: int == 29;
}
t: @cpp1_rule_of_zero <T> specialize<* T> type = {
public v: int == 17;
public f: () = 29;
}
u: @cpp1_rule_of_zero <T...> type = {
public a: i32 = 1;
}
u: @cpp1_rule_of_zero specialize<> type = {
public a: i32 = 2;
}
u: specialize<i16> type = { }
v: <T> const i32 = 1;
v: <> specialize<void> const i32 = 2;
v: specialize<i64> const i32 = 3;
v: specialize<i16> std::optional<i32> == 4;
v: <> specialize<i8> std::optional<i8> == 5;
v: <T> specialize<* T> std::optional<int> == 6;
main: () = {
assert(t<i32>().a == 1);
assert(t<void>().b == 2);
assert(t<i64>().c == 3);
assert(t<* i8>::f() == 17);
assert(t<* i8>::v == 29);
assert(t<* i16>::v == 17);
assert(t<* i16>::f() == 29);
assert(u<i32>().a == 1);
assert(u<>().a == 1);
assert(v<i32> == 1);
assert(v<void> == 2);
assert(v<i64> == 3);
static_assert(v<i16> == 4);
static_assert(v<i8> == 5);
static_assert(v<* int> == 6);
}
3 changes: 3 additions & 0 deletions regression-tests/test-results/pure2-alias-1-error.cpp2.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pure2-alias-1-error.cpp2...
pure2-alias-1-error.cpp2(1,19): error: a namespace or namespace alias cannot have template parameters

3 changes: 3 additions & 0 deletions regression-tests/test-results/pure2-alias-2-error.cpp2.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pure2-alias-2-error.cpp2...
pure2-alias-2-error.cpp2(1,15): error: 'requires' is not allowed on a namespace alias (at 'requires')

3 changes: 3 additions & 0 deletions regression-tests/test-results/pure2-alias-3-error.cpp2.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pure2-alias-3-error.cpp2...
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 changes: 3 additions & 0 deletions regression-tests/test-results/pure2-alias-4-error.cpp2.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pure2-alias-4-error.cpp2...
pure2-alias-4-error.cpp2(1,18): error: a type alias cannot be specialized

3 changes: 3 additions & 0 deletions regression-tests/test-results/pure2-alias-5-error.cpp2.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pure2-alias-5-error.cpp2...
pure2-alias-5-error.cpp2(1,18): error: a namespace alias cannot be specialized

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pure2-namespace-1-error.cpp2...
pure2-namespace-1-error.cpp2(1,19): error: a namespace or namespace alias cannot have template parameters

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pure2-namespace-2-error.cpp2...
pure2-namespace-2-error.cpp2(1,15): error: 'requires' is not allowed on a namespace alias (at 'requires')

27 changes: 27 additions & 0 deletions regression-tests/test-results/pure2-print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@
#line 6 "pure2-print.cpp2"
class outer;

#line 107 "pure2-print.cpp2"
namespace std {

#line 111 "pure2-print.cpp2"
namespace numbers {

}
}


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

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

namespace std {
template<> class common_type<outer,outer> {
public: using type = outer;
};
namespace numbers {
/*@print*/
}
}

auto main() -> int;

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

#line 107 "pure2-print.cpp2"
namespace std {

#line 111 "pure2-print.cpp2"
namespace numbers {
template<> double const pi_v<outer> {pi_v<double>};
}
}

#line 116 "pure2-print.cpp2"
auto main() -> int{
outer::test();
}
Expand Down
6 changes: 6 additions & 0 deletions regression-tests/test-results/pure2-print.cpp2.output
Original file line number Diff line number Diff line change
Expand Up @@ -151,5 +151,11 @@ outer:/* @print */ type =
{
}
}


common_type:/* @struct @print */ specialize<outer, outer> type =
{
public type: type == outer;
}
ok (all Cpp2, passes safety checks)

94 changes: 94 additions & 0 deletions regression-tests/test-results/pure2-template-specialization.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@

#define CPP2_IMPORT_STD Yes

//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"

#line 1 "pure2-template-specialization.cpp2"
template<typename T> class t;
#line 2 "pure2-template-specialization.cpp2"


#line 18 "pure2-template-specialization.cpp2"
template<typename ...T> class u;


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

#line 1 "pure2-template-specialization.cpp2"
template<typename T> class t {
#line 2 "pure2-template-specialization.cpp2"
public: cpp2::i32 a {1};
};
template<typename T> requires( std::is_void_v<T> )
class t<T> {public: cpp2::i32 b {2};
};
template<> class t<cpp2::i64> {
public: cpp2::i32 c {3};
};
template<> class t<cpp2::i8*> {
public: [[nodiscard]] static auto f() -> decltype(auto);
public: static const int v;
};
template<typename T> class t<T*> {
public: static const int v;
public: [[nodiscard]] static auto f() -> decltype(auto);
};
template<typename ...T> class u {
public: cpp2::i32 a {1};
};
template<> class u<> {
public: cpp2::i32 a {2};
};
template<> class u<cpp2::i16> {
public: u() = default;
public: u(u const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(u const&) -> void = delete;
};
#line 25 "pure2-template-specialization.cpp2"
template<typename T> extern cpp2::i32 const v;

#line 28 "pure2-template-specialization.cpp2"
template<> std::optional<cpp2::i32> inline constexpr v<cpp2::i16>{ 4 };
template<> std::optional<cpp2::i8> inline constexpr v<cpp2::i8>{ 5 };
template<typename T> std::optional<int> inline constexpr v<T*>{ 6 };
auto main() -> int;

//=== Cpp2 function definitions =================================================

#line 1 "pure2-template-specialization.cpp2"

#line 11 "pure2-template-specialization.cpp2"
[[nodiscard]] auto t<cpp2::i8*>::f() -> decltype(auto) { return 17; }
inline CPP2_CONSTEXPR int t<cpp2::i8*>::v{ 29 };

#line 15 "pure2-template-specialization.cpp2"
template <typename T> inline CPP2_CONSTEXPR int t<T*>::v{ 17 };
template <typename T> [[nodiscard]] auto t<T*>::f() -> decltype(auto) { return 29; }

#line 25 "pure2-template-specialization.cpp2"
template<typename T> cpp2::i32 const v {1};
template<> cpp2::i32 const v<void> {2};
template<> cpp2::i32 const v<cpp2::i64> {3};

#line 31 "pure2-template-specialization.cpp2"
auto main() -> int{
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i32>().a == 1) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(t<void>().b == 2) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i64>().c == 3) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i8*>::f() == 17) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i8*>::v == 29) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i16*>::v == 17) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(t<cpp2::i16*>::f() == 29) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(u<cpp2::i32>().a == 1) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(u<>().a == 1) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(v<cpp2::i32> == 1) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(v<void> == 2) ) { cpp2::cpp2_default.report_violation(""); }
if (cpp2::cpp2_default.is_active() && !(v<cpp2::i64> == 3) ) { cpp2::cpp2_default.report_violation(""); }
static_assert(v<cpp2::i16> == 4);
static_assert(v<cpp2::i8> == 5);
static_assert(v<int*> == 6);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pure2-template-specialization.cpp2... ok (all Cpp2, passes safety checks)

Loading

0 comments on commit fd2dab7

Please sign in to comment.