Skip to content

Commit c4e00a0

Browse files
committed
feat(reflect): add @rule_of_zero
1 parent 083c8a0 commit c4e00a0

File tree

1 file changed

+56
-22
lines changed

1 file changed

+56
-22
lines changed

source/reflect.h2

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ compiler_services: @polymorphic_base @copyable type =
8484

8585
// First split this string into source_lines
8686
//
87-
(copy newline_pos := source.find('\n'))
87+
(copy newline_pos := source.find('\n'))
8888
if source.ssize() > 1
8989
&& newline_pos != source.npos
9090
{
@@ -281,7 +281,7 @@ declaration: @polymorphic_base @copyable type =
281281
parent_is_alias : (this) -> bool = n*.parent_is_alias();
282282
parent_is_polymorphic: (this) -> bool = n*.parent_is_polymorphic();
283283

284-
mark_for_removal_from_enclosing_type: (inout this)
284+
mark_for_removal_from_enclosing_type: (inout this)
285285
[[pre Type: parent_is_type()]] // this precondition should be sufficient ...
286286
= {
287287
test := n*.type_member_mark_for_removal();
@@ -400,7 +400,7 @@ type_declaration: @copyable type =
400400
[[assert: n*.is_type()]]
401401
}
402402

403-
reserve_names: (this, name: std::string_view, forward etc...) =
403+
reserve_names: (this, name: std::string_view, forward etc...) =
404404
{ // etc is not declared ':string_view' for compatibility with GCC 10.x
405405
for get_members()
406406
do (m) {
@@ -752,7 +752,7 @@ basic_value: (inout t: meta::type_declaration) =
752752
//-----------------------------------------------------------------------
753753
//
754754
// "A 'value' is a totally ordered basic_value..."
755-
//
755+
//
756756
// -- P0707R4, section 3
757757
//
758758
// value - a value type that is totally ordered
@@ -778,6 +778,40 @@ partially_ordered_value: (inout t: meta::type_declaration) =
778778
}
779779

780780

781+
//-----------------------------------------------------------------------
782+
//
783+
// C.20: If you can avoid defining default operations, do
784+
//
785+
// ##### Reason
786+
//
787+
// It's the simplest and gives the cleanest semantics.
788+
//
789+
// ...
790+
//
791+
// This is known as "the rule of zero".
792+
//
793+
// -- C++ Core Guidelines
794+
// C.20: If you can avoid defining any default operations, do
795+
// <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-zero>
796+
//
797+
//-----------------------------------------------------------------------
798+
//
799+
// rule_of_zero
800+
//
801+
// a type without declared copy/move/destructor functions
802+
//
803+
rule_of_zero: (inout t: meta::type_declaration) =
804+
{
805+
for t.get_member_functions() do (inout mf)
806+
{
807+
t.require( !mf.is_constructor_with_that()
808+
&& !mf.is_assignment_with_that()
809+
&& !mf.is_destructor(),
810+
"the rule of zero requires no copy/move/destructor functions");
811+
}
812+
t.disable_member_function_generation();
813+
}
814+
781815
//-----------------------------------------------------------------------
782816
//
783817
// "By definition, a `struct` is a `class` in which members
@@ -817,7 +851,7 @@ struct: (inout t: meta::type_declaration) =
817851
"a struct may not have a user-defined operator=");
818852
}
819853
}
820-
t.disable_member_function_generation();
854+
t.rule_of_zero();
821855
}
822856

823857

@@ -904,7 +938,7 @@ basic_enum: (
904938
}
905939

906940
// Compute the default underlying type, if it wasn't explicitly specified
907-
if underlying_type == ""
941+
if underlying_type == ""
908942
{
909943
t.require( !found_non_numeric,
910944
"if you write an enumerator with a non-numeric-literal value, you must specify the enumeration's underlying type");
@@ -987,7 +1021,7 @@ basic_enum: (
9871021
to_string += " if this == none { return \"(none)\"; }\n";
9881022
}
9891023

990-
for enumerators
1024+
for enumerators
9911025
do (e) {
9921026
if e.name != "_" { // ignore unnamed values
9931027
if bitwise {
@@ -1019,7 +1053,7 @@ basic_enum: (
10191053
// value of its enumerators's type, and otherwise has only public
10201054
// member variables of its enumerator's type, all of which are
10211055
// naturally scoped because they are members of a type."
1022-
//
1056+
//
10231057
// -- P0707R4, section 3
10241058
//
10251059
enum: (inout t: meta::type_declaration) =
@@ -1041,12 +1075,12 @@ enum: (inout t: meta::type_declaration) =
10411075

10421076
//-----------------------------------------------------------------------
10431077
//
1044-
// "flag_enum expresses an enumeration that stores values
1078+
// "flag_enum expresses an enumeration that stores values
10451079
// corresponding to bitwise-or'd enumerators. The enumerators must
10461080
// be powers of two, and are automatically generated [...] A none
10471081
// value is provided [...] Operators | and & are provided to
10481082
// combine and extract values."
1049-
//
1083+
//
10501084
// -- P0707R4, section 3
10511085
//
10521086
flag_enum: (inout t: meta::type_declaration) =
@@ -1079,10 +1113,10 @@ flag_enum: (inout t: meta::type_declaration) =
10791113
//
10801114
// -- Stroustrup (The Design and Evolution of C++, 14.3.4.1)
10811115
//
1082-
// "C++17 needs a type-safe union... The implications of the
1083-
// consensus `variant` design are well understood and have been
1084-
// explored over several LEWG discussions, over a thousand emails,
1085-
// a joint LEWG/EWG session, and not to mention 12 years of
1116+
// "C++17 needs a type-safe union... The implications of the
1117+
// consensus `variant` design are well understood and have been
1118+
// explored over several LEWG discussions, over a thousand emails,
1119+
// a joint LEWG/EWG session, and not to mention 12 years of
10861120
// experience with Boost and other libraries."
10871121
//
10881122
// -- Axel Naumann, in P0088 (wg21.link/p0088),
@@ -1091,9 +1125,9 @@ flag_enum: (inout t: meta::type_declaration) =
10911125
//-----------------------------------------------------------------------
10921126
//
10931127
// union
1094-
//
1128+
//
10951129
// a type that contains exactly one of a fixed set of values at a time
1096-
//
1130+
//
10971131

10981132
union: (inout t : meta::type_declaration)
10991133
= {
@@ -1148,8 +1182,8 @@ union: (inout t : meta::type_declaration)
11481182
(copy storage: std::string = " _storage: std::aligned_storage_t<cpp2::max( ")
11491183
{
11501184
(copy comma: std::string = "")
1151-
for alternatives
1152-
next comma = ", "
1185+
for alternatives
1186+
next comma = ", "
11531187
do (e) {
11541188
storage += comma + "sizeof((e.type)$)";
11551189
}
@@ -1162,7 +1196,7 @@ union: (inout t : meta::type_declaration)
11621196
t.add_member( " _discriminator: (discriminator_type)$ = -1;\n");
11631197

11641198
// Add the alternatives: is_alternative, get_alternative, and set_alternative
1165-
for alternatives
1199+
for alternatives
11661200
do (a)
11671201
{
11681202
t.add_member( " is_(a.name)$: (this) -> bool = _discriminator == (a.value)$;\n");
@@ -1252,7 +1286,7 @@ apply_metafunctions: (
12521286

12531287
args: std::vector<std::string> = ();
12541288
for meta*.template_arguments()
1255-
do (arg)
1289+
do (arg)
12561290
args.push_back( arg.to_string() );
12571291

12581292
rtype.set_metafunction_name( name, args );
@@ -1311,9 +1345,9 @@ apply_metafunctions: (
13111345
}
13121346

13131347
if (
1314-
!args.empty()
1348+
!args.empty()
13151349
&& !rtype.arguments_were_used()
1316-
)
1350+
)
13171351
{
13181352
error( name + " did not use its template arguments - did you mean to write '" + name + " <" + args[0] + "> type' (with the spaces)?");
13191353
return false;

0 commit comments

Comments
 (0)