@@ -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//
10251059enum: (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//
10521086flag_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
10981132union: (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