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 2, 2024
1 parent c5feb42 commit 12ad062
Show file tree
Hide file tree
Showing 8 changed files with 293 additions and 29 deletions.
9 changes: 9 additions & 0 deletions regression-tests/pure2-print.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,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();
}
38 changes: 38 additions & 0 deletions regression-tests/pure2-template-specialization.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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;
}
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(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);
}
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 105 "pure2-print.cpp2"
namespace std {

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

}
}


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

Expand Down Expand Up @@ -78,6 +87,15 @@ CPP2_REQUIRES_ (cpp2::impl::cmp_greater_eq(sizeof...(Args),0u)) ;
#line 103 "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 @@ -200,6 +218,15 @@ requires (cpp2::impl::cmp_greater_eq(sizeof...(Args),0u)) {
return (... && args); }

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

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

#line 114 "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 @@ -147,5 +147,11 @@ outer:/* @print */ type =

all: <Args...: type, >(in args...: Args, ) -> move bool = (... && args);
}


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

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

#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"


//=== 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() -> auto;
public: static const int v;
};
template<typename T> class t<T*> {
public: static const int v;
public: [[nodiscard]] static auto f() -> auto;
};
template<typename T> extern cpp2::i32 const v;

#line 21 "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() -> 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() -> auto { return 29; }

#line 18 "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 24 "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() && !(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 12ad062

Please sign in to comment.