@@ -84,7 +84,7 @@ compiler_services: @polymorphic_base @copyable type =
84
84
85
85
// First split this string into source_lines
86
86
//
87
- (copy newline_pos := source.find('\n'))
87
+ (copy newline_pos := source.find('\n'))
88
88
if source.ssize() > 1
89
89
&& newline_pos != source.npos
90
90
{
@@ -281,7 +281,7 @@ declaration: @polymorphic_base @copyable type =
281
281
parent_is_alias : (this) -> bool = n*.parent_is_alias();
282
282
parent_is_polymorphic: (this) -> bool = n*.parent_is_polymorphic();
283
283
284
- mark_for_removal_from_enclosing_type: (inout this)
284
+ mark_for_removal_from_enclosing_type: (inout this)
285
285
[[pre Type: parent_is_type()]] // this precondition should be sufficient ...
286
286
= {
287
287
test := n*.type_member_mark_for_removal();
@@ -400,7 +400,7 @@ type_declaration: @copyable type =
400
400
[[assert: n*.is_type()]]
401
401
}
402
402
403
- reserve_names: (this, name: std::string_view, forward etc...) =
403
+ reserve_names: (this, name: std::string_view, forward etc...) =
404
404
{ // etc is not declared ':string_view' for compatibility with GCC 10.x
405
405
for get_members()
406
406
do (m) {
@@ -752,7 +752,7 @@ basic_value: (inout t: meta::type_declaration) =
752
752
//-----------------------------------------------------------------------
753
753
//
754
754
// "A 'value' is a totally ordered basic_value..."
755
- //
755
+ //
756
756
// -- P0707R4, section 3
757
757
//
758
758
// value - a value type that is totally ordered
@@ -778,6 +778,40 @@ partially_ordered_value: (inout t: meta::type_declaration) =
778
778
}
779
779
780
780
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
+
781
815
//-----------------------------------------------------------------------
782
816
//
783
817
// "By definition, a `struct` is a `class` in which members
@@ -817,7 +851,7 @@ struct: (inout t: meta::type_declaration) =
817
851
"a struct may not have a user-defined operator=");
818
852
}
819
853
}
820
- t.disable_member_function_generation ();
854
+ t.rule_of_zero ();
821
855
}
822
856
823
857
@@ -904,7 +938,7 @@ basic_enum: (
904
938
}
905
939
906
940
// Compute the default underlying type, if it wasn't explicitly specified
907
- if underlying_type == ""
941
+ if underlying_type == ""
908
942
{
909
943
t.require( !found_non_numeric,
910
944
"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: (
987
1021
to_string += " if this == none { return \"(none)\"; }\n";
988
1022
}
989
1023
990
- for enumerators
1024
+ for enumerators
991
1025
do (e) {
992
1026
if e.name != "_" { // ignore unnamed values
993
1027
if bitwise {
@@ -1019,7 +1053,7 @@ basic_enum: (
1019
1053
// value of its enumerators's type, and otherwise has only public
1020
1054
// member variables of its enumerator's type, all of which are
1021
1055
// naturally scoped because they are members of a type."
1022
- //
1056
+ //
1023
1057
// -- P0707R4, section 3
1024
1058
//
1025
1059
enum: (inout t: meta::type_declaration) =
@@ -1041,12 +1075,12 @@ enum: (inout t: meta::type_declaration) =
1041
1075
1042
1076
//-----------------------------------------------------------------------
1043
1077
//
1044
- // "flag_enum expresses an enumeration that stores values
1078
+ // "flag_enum expresses an enumeration that stores values
1045
1079
// corresponding to bitwise-or'd enumerators. The enumerators must
1046
1080
// be powers of two, and are automatically generated [...] A none
1047
1081
// value is provided [...] Operators | and & are provided to
1048
1082
// combine and extract values."
1049
- //
1083
+ //
1050
1084
// -- P0707R4, section 3
1051
1085
//
1052
1086
flag_enum: (inout t: meta::type_declaration) =
@@ -1079,10 +1113,10 @@ flag_enum: (inout t: meta::type_declaration) =
1079
1113
//
1080
1114
// -- Stroustrup (The Design and Evolution of C++, 14.3.4.1)
1081
1115
//
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
1086
1120
// experience with Boost and other libraries."
1087
1121
//
1088
1122
// -- Axel Naumann, in P0088 (wg21.link/p0088),
@@ -1091,9 +1125,9 @@ flag_enum: (inout t: meta::type_declaration) =
1091
1125
//-----------------------------------------------------------------------
1092
1126
//
1093
1127
// union
1094
- //
1128
+ //
1095
1129
// a type that contains exactly one of a fixed set of values at a time
1096
- //
1130
+ //
1097
1131
1098
1132
union: (inout t : meta::type_declaration)
1099
1133
= {
@@ -1148,8 +1182,8 @@ union: (inout t : meta::type_declaration)
1148
1182
(copy storage: std::string = " _storage: std::aligned_storage_t<cpp2::max( ")
1149
1183
{
1150
1184
(copy comma: std::string = "")
1151
- for alternatives
1152
- next comma = ", "
1185
+ for alternatives
1186
+ next comma = ", "
1153
1187
do (e) {
1154
1188
storage += comma + "sizeof((e.type)$)";
1155
1189
}
@@ -1162,7 +1196,7 @@ union: (inout t : meta::type_declaration)
1162
1196
t.add_member( " _discriminator: (discriminator_type)$ = -1;\n");
1163
1197
1164
1198
// Add the alternatives: is_alternative, get_alternative, and set_alternative
1165
- for alternatives
1199
+ for alternatives
1166
1200
do (a)
1167
1201
{
1168
1202
t.add_member( " is_(a.name)$: (this) -> bool = _discriminator == (a.value)$;\n");
@@ -1252,7 +1286,7 @@ apply_metafunctions: (
1252
1286
1253
1287
args: std::vector<std::string> = ();
1254
1288
for meta*.template_arguments()
1255
- do (arg)
1289
+ do (arg)
1256
1290
args.push_back( arg.to_string() );
1257
1291
1258
1292
rtype.set_metafunction_name( name, args );
@@ -1289,6 +1323,9 @@ apply_metafunctions: (
1289
1323
else if name == "partially_ordered_value" {
1290
1324
partially_ordered_value( rtype );
1291
1325
}
1326
+ else if name == "rule_of_zero" {
1327
+ rule_of_zero( rtype );
1328
+ }
1292
1329
else if name == "struct" {
1293
1330
cpp2_struct( rtype );
1294
1331
}
@@ -1306,14 +1343,14 @@ apply_metafunctions: (
1306
1343
}
1307
1344
else {
1308
1345
error( "unrecognized metafunction name: " + name );
1309
- error( "(temporary alpha limitation) currently the supported names are: interface, polymorphic_base, ordered, weakly_ordered, partially_ordered, copyable, basic_value, value, weakly_ordered_value, partially_ordered_value, struct, enum, flag_enum, union, print" );
1346
+ error( "(temporary alpha limitation) currently the supported names are: interface, polymorphic_base, ordered, weakly_ordered, partially_ordered, copyable, basic_value, value, weakly_ordered_value, partially_ordered_value, rule_of_zero, struct, enum, flag_enum, union, print" );
1310
1347
return false;
1311
1348
}
1312
1349
1313
1350
if (
1314
- !args.empty()
1351
+ !args.empty()
1315
1352
&& !rtype.arguments_were_used()
1316
- )
1353
+ )
1317
1354
{
1318
1355
error( name + " did not use its template arguments - did you mean to write '" + name + " <" + args[0] + "> type' (with the spaces)?");
1319
1356
return false;
0 commit comments