Skip to content

Commit 4641ad2

Browse files
committed
Add @hashable metafunction
Adds a `hash() -> size_t` function Memberwise semantics, using `std::hash` for data members and `base::hash` for base classes
1 parent d3635e6 commit 4641ad2

File tree

15 files changed

+617
-402
lines changed

15 files changed

+617
-402
lines changed

include/cpp2util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ using constness_like_t =
852852
>;
853853

854854
template<class T, class U>
855-
[[nodiscard]] constexpr auto&& forward_like(U&& x) noexcept
855+
[[nodiscard]] constexpr auto forward_like(U&& x) noexcept -> decltype(auto)
856856
{
857857
constexpr bool is_adding_const = std::is_const_v<std::remove_reference_t<T>>;
858858
if constexpr (std::is_lvalue_reference_v<T&&>)

regression-tests/pure2-hashable.cpp2

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
base: @struct @hashable type = {
2+
h: i32;
3+
}
4+
5+
mystruct: @struct @hashable type = {
6+
this: base = (1);
7+
i: i32;
8+
j: std::string;
9+
k: u64;
10+
}
11+
12+
main: () = {
13+
x: mystruct = (2, "three", 4u);
14+
std::cout << x.hash();
15+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10166087914140344613
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
pure2-hashable.cpp2:3:27: error: expected ‘;’ at end of member declaration
2+
In file included from pure2-hashable.cpp:7:
3+
../../../include/cpp2util.h:10005:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.
4+
pure2-hashable.cpp2:4:1: note: in expansion of macro ‘CPP2_REQUIRES_’
5+
pure2-hashable.cpp2:6:42: error: expected ‘;’ at end of member declaration
6+
In file included from pure2-hashable.cpp:7:
7+
../../../include/cpp2util.h:10005:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.
8+
pure2-hashable.cpp2:7:1: note: in expansion of macro ‘CPP2_REQUIRES_’
9+
pure2-hashable.cpp2:10:53: error: expected ‘;’ at end of member declaration
10+
In file included from pure2-hashable.cpp:7:
11+
../../../include/cpp2util.h:10005:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.
12+
pure2-hashable.cpp2:11:1: note: in expansion of macro ‘CPP2_REQUIRES_’
13+
pure2-hashable.cpp2:3:1: error: no declaration matches ‘base::base(auto:101&&) requires is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(base::__ct ::h_)>::type>::type, const std::add_const_t&>’
14+
pure2-hashable.cpp2:1:7: note: candidates are: ‘constexpr base::base(base&&)’
15+
pure2-hashable.cpp2:1:7: note: ‘constexpr base::base(const base&)’
16+
pure2-hashable.cpp2:3:13: note: ‘template<class auto:96> base::base(auto:96&&)’
17+
pure2-hashable.cpp2:1:7: note: ‘class base’ defined here
18+
pure2-hashable.cpp2:5:83: error: expected unqualified-id before ‘{’ token
19+
pure2-hashable.cpp2:6:6: error: no declaration matches ‘base& base::operator=(auto:102&&) requires is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(base::operator=::h_)>::type>::type, const std::add_const_t&>’
20+
pure2-hashable.cpp2:1:7: note: candidates are: ‘constexpr base& base::operator=(base&&)’
21+
pure2-hashable.cpp2:1:7: note: ‘constexpr base& base::operator=(const base&)’
22+
pure2-hashable.cpp2:6:14: note: ‘template<class auto:97> base& base::operator=(auto:97&&)’
23+
pure2-hashable.cpp2:1:7: note: ‘class base’ defined here
24+
pure2-hashable.cpp2:11:1: error: no declaration matches ‘mystruct::mystruct(auto:103&&, auto:104&&, auto:105&&) requires (is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(mystruct::__ct ::i_)>::type>::type, const std::add_const_t&>) && (is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(mystruct::__ct ::j_)>::type>::type, const std::__cxx11::add_const_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&>) && (is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(mystruct::__ct ::k_)>::type>::type, const std::add_const_t&>)’
25+
pure2-hashable.cpp2:5:7: note: candidates are: ‘mystruct::mystruct(mystruct&&)’
26+
pure2-hashable.cpp2:5:7: note: ‘mystruct::mystruct(const mystruct&)’
27+
pure2-hashable.cpp2:10:13: note: ‘template<class auto:98, class auto:99, class auto:100> mystruct::mystruct(auto:98&&, auto:99&&, auto:100&&)’
28+
pure2-hashable.cpp2:5:7: note: ‘class mystruct’ defined here
29+
pure2-hashable.cpp2:14:104: error: mixing declarations and function-definitions is forbidden
30+
pure2-hashable.cpp2:14:107: error: expected constructor, destructor, or type conversion before ‘{’ token
31+
pure2-hashable.cpp2:15:104: error: expected unqualified-id before ‘,’ token
32+
pure2-hashable.cpp2:15:107: error: expected constructor, destructor, or type conversion before ‘{’ token
33+
pure2-hashable.cpp2:16:104: error: expected unqualified-id before ‘,’ token
34+
pure2-hashable.cpp2:16:107: error: expected constructor, destructor, or type conversion before ‘{’ token
35+
pure2-hashable.cpp2:16:127: error: expected unqualified-id before ‘{’ token

regression-tests/test-results/gcc-14-c++2b/gcc-version.output

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
g++ (GCC) 14.2.1 20240801 (Red Hat 14.2.1-1)
1+
g++ (GCC) 14.2.1 20240912 (Red Hat 14.2.1-3)
22
Copyright (C) 2024 Free Software Foundation, Inc.
33
This is free software; see the source for copying conditions. There is NO
44
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10166087914140344613
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
13273923326899311054
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pure2-hashable.cpp
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
2+
#define CPP2_IMPORT_STD Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
#line 1 "pure2-hashable.cpp2"
10+
class base;
11+
#line 2 "pure2-hashable.cpp2"
12+
13+
14+
#line 5 "pure2-hashable.cpp2"
15+
class mystruct;
16+
17+
18+
//=== Cpp2 type definitions and function declarations ===========================
19+
20+
#line 1 "pure2-hashable.cpp2"
21+
class base {
22+
#line 2 "pure2-hashable.cpp2"
23+
public: cpp2::i32 h;
24+
public: base(auto&& h_)
25+
CPP2_REQUIRES_ (std::is_convertible_v<CPP2_TYPEOF(h_), std::add_const_t<cpp2::i32>&>) ;
26+
27+
public: auto operator=(auto&& h_) -> base&
28+
CPP2_REQUIRES_ (std::is_convertible_v<CPP2_TYPEOF(h_), std::add_const_t<cpp2::i32>&>) ;
29+
public: [[nodiscard]] auto hash() const& -> size_t;
30+
31+
#line 3 "pure2-hashable.cpp2"
32+
};
33+
34+
class mystruct: public base {
35+
36+
public: cpp2::i32 i;
37+
public: std::string j;
38+
public: cpp2::u64 k;
39+
public: mystruct(auto&& i_, auto&& j_, auto&& k_)
40+
CPP2_REQUIRES_ (std::is_convertible_v<CPP2_TYPEOF(i_), std::add_const_t<cpp2::i32>&> && std::is_convertible_v<CPP2_TYPEOF(j_), std::add_const_t<std::string>&> && std::is_convertible_v<CPP2_TYPEOF(k_), std::add_const_t<cpp2::u64>&>) ;
41+
public: [[nodiscard]] auto hash() const& -> size_t;
42+
43+
#line 10 "pure2-hashable.cpp2"
44+
};
45+
46+
auto main() -> int;
47+
48+
//=== Cpp2 function definitions =================================================
49+
50+
#line 1 "pure2-hashable.cpp2"
51+
52+
53+
base::base(auto&& h_)
54+
requires (std::is_convertible_v<CPP2_TYPEOF(h_), std::add_const_t<cpp2::i32>&>)
55+
: h{ CPP2_FORWARD(h_) }{}
56+
auto base::operator=(auto&& h_) -> base&
57+
requires (std::is_convertible_v<CPP2_TYPEOF(h_), std::add_const_t<cpp2::i32>&>) {
58+
h = CPP2_FORWARD(h_);
59+
return *this;}
60+
[[nodiscard]] auto base::hash() const& -> size_t { return std::hash<cpp2::i32>()(h); }
61+
mystruct::mystruct(auto&& i_, auto&& j_, auto&& k_)
62+
requires (std::is_convertible_v<CPP2_TYPEOF(i_), std::add_const_t<cpp2::i32>&> && std::is_convertible_v<CPP2_TYPEOF(j_), std::add_const_t<std::string>&> && std::is_convertible_v<CPP2_TYPEOF(k_), std::add_const_t<cpp2::u64>&>)
63+
: base{ (1) }
64+
, i{ CPP2_FORWARD(i_) }
65+
, j{ CPP2_FORWARD(j_) }
66+
, k{ CPP2_FORWARD(k_) }{}
67+
[[nodiscard]] auto mystruct::hash() const& -> size_t { return base::hash() ^ (std::hash<cpp2::i32>()(i) << 1) ^ (std::hash<std::string>()(j) << 2) ^ (std::hash<cpp2::u64>()(k) << 3); }
68+
#line 12 "pure2-hashable.cpp2"
69+
auto main() -> int{
70+
mystruct x {2, "three", 4u};
71+
std::cout << CPP2_UFCS(hash)(cpp2::move(x));
72+
}
73+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-hashable.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.4 Build 9922:0658
2+
cppfront compiler v0.7.4 Build 9930:1028
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-
"9922:0658"
1+
"9930:1028"

source/parse.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -749,8 +749,8 @@ struct expression_list_node
749749
ret += term.expr->to_string();
750750
}
751751

752-
if (open_paren) {
753-
ret += *open_paren;
752+
if (close_paren) {
753+
ret += *close_paren;
754754
}
755755

756756
return ret;

0 commit comments

Comments
 (0)