Skip to content

Commit e599f74

Browse files
committed
feat(reflect): add @rule_of_zero
1 parent 7fff368 commit e599f74

File tree

2 files changed

+123
-45
lines changed

2 files changed

+123
-45
lines changed

source/reflect.h

Lines changed: 80 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ class type_declaration;
3636
#line 589 "reflect.h2"
3737
class alias_declaration;
3838

39-
#line 928 "reflect.h2"
39+
#line 962 "reflect.h2"
4040
class value_member_info;
4141

42-
#line 1445 "reflect.h2"
42+
#line 1482 "reflect.h2"
4343
}
4444

4545
}
@@ -621,6 +621,31 @@ auto partially_ordered_value(meta::type_declaration& t) -> void;
621621
#line 868 "reflect.h2"
622622
//-----------------------------------------------------------------------
623623
//
624+
// C.20: If you can avoid defining default operations, do
625+
//
626+
// ##### Reason
627+
//
628+
// It's the simplest and gives the cleanest semantics.
629+
//
630+
// ...
631+
//
632+
// This is known as "the rule of zero".
633+
//
634+
// -- C++ Core Guidelines
635+
// C.20: If you can avoid defining any default operations, do
636+
// <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-zero>
637+
//
638+
//-----------------------------------------------------------------------
639+
//
640+
// rule_of_zero
641+
//
642+
// a type without declared copy/move/destructor functions
643+
//
644+
auto rule_of_zero(meta::type_declaration& t) -> void;
645+
646+
#line 902 "reflect.h2"
647+
//-----------------------------------------------------------------------
648+
//
624649
// "By definition, a `struct` is a `class` in which members
625650
// are by default `public`; that is,
626651
//
@@ -646,7 +671,7 @@ auto partially_ordered_value(meta::type_declaration& t) -> void;
646671
//
647672
auto cpp2_struct(meta::type_declaration& t) -> void;
648673

649-
#line 911 "reflect.h2"
674+
#line 945 "reflect.h2"
650675
//-----------------------------------------------------------------------
651676
//
652677
// "C enumerations constitute a curiously half-baked concept. ...
@@ -676,7 +701,7 @@ auto basic_enum(
676701
cpp2::in<bool> bitwise
677702
) -> void;
678703

679-
#line 1117 "reflect.h2"
704+
#line 1151 "reflect.h2"
680705
//-----------------------------------------------------------------------
681706
//
682707
// "An enum[...] is a totally ordered value type that stores a
@@ -688,7 +713,7 @@ auto basic_enum(
688713
//
689714
auto cpp2_enum(meta::type_declaration& t) -> void;
690715

691-
#line 1143 "reflect.h2"
716+
#line 1177 "reflect.h2"
692717
//-----------------------------------------------------------------------
693718
//
694719
// "flag_enum expresses an enumeration that stores values
@@ -701,7 +726,7 @@ auto cpp2_enum(meta::type_declaration& t) -> void;
701726
//
702727
auto flag_enum(meta::type_declaration& t) -> void;
703728

704-
#line 1175 "reflect.h2"
729+
#line 1209 "reflect.h2"
705730
//-----------------------------------------------------------------------
706731
//
707732
// "As with void*, programmers should know that unions [...] are
@@ -728,14 +753,14 @@ auto flag_enum(meta::type_declaration& t) -> void;
728753

729754
auto cpp2_union(meta::type_declaration& t) -> void;
730755

731-
#line 1331 "reflect.h2"
756+
#line 1365 "reflect.h2"
732757
//-----------------------------------------------------------------------
733758
//
734759
// print - output a pretty-printed visualization of t
735760
//
736761
auto print(cpp2::in<meta::type_declaration> t) -> void;
737762

738-
#line 1341 "reflect.h2"
763+
#line 1375 "reflect.h2"
739764
//-----------------------------------------------------------------------
740765
//
741766
// apply_metafunctions
@@ -746,7 +771,7 @@ auto print(cpp2::in<meta::type_declaration> t) -> void;
746771
auto const& error
747772
) -> bool;
748773

749-
#line 1445 "reflect.h2"
774+
#line 1482 "reflect.h2"
750775
}
751776

752777
}
@@ -1081,7 +1106,7 @@ declaration::declaration(declaration const& that)
10811106
{
10821107
if ((*this).has_handler() && !(!(has_initializer())) ) { (*this).report_violation(CPP2_CONTRACT_MSG("cannot add an initializer to a function that already has one")); }
10831108
if ((*this).has_handler() && !(parent_is_type()) ) { (*this).report_violation(CPP2_CONTRACT_MSG("cannot add an initializer to a function that isn't in a type scope")); }
1084-
//require( !has_initializer(),
1109+
//require( !has_initializer(),
10851110
// "cannot add an initializer to a function that already has one");
10861111
//require( parent_is_type(),
10871112
// "cannot add an initializer to a function that isn't in a type scope");
@@ -1442,7 +1467,20 @@ auto partially_ordered_value(meta::type_declaration& t) -> void
14421467
CPP2_UFCS(basic_value)(t);
14431468
}
14441469

1445-
#line 893 "reflect.h2"
1470+
#line 890 "reflect.h2"
1471+
auto rule_of_zero(meta::type_declaration& t) -> void
1472+
{
1473+
for ( auto& mf : CPP2_UFCS(get_member_functions)(t) )
1474+
{
1475+
CPP2_UFCS(require)(t, !(CPP2_UFCS(is_constructor_with_that)(mf))
1476+
&& !(CPP2_UFCS(is_assignment_with_that)(mf))
1477+
&& !(CPP2_UFCS(is_destructor)(mf)),
1478+
"the rule of zero requires no copy/move/destructor functions");
1479+
}
1480+
CPP2_UFCS(disable_member_function_generation)(t);
1481+
}
1482+
1483+
#line 927 "reflect.h2"
14461484
auto cpp2_struct(meta::type_declaration& t) -> void
14471485
{
14481486
for ( auto& m : CPP2_UFCS(get_members)(t) )
@@ -1457,10 +1495,10 @@ auto cpp2_struct(meta::type_declaration& t) -> void
14571495
"a struct may not have a user-defined operator=");
14581496
}
14591497
}
1460-
CPP2_UFCS(disable_member_function_generation)(t);
1498+
CPP2_UFCS(rule_of_zero)(t);
14611499
}
14621500

1463-
#line 934 "reflect.h2"
1501+
#line 968 "reflect.h2"
14641502
auto basic_enum(
14651503
meta::type_declaration& t,
14661504
auto const& nextval,
@@ -1485,7 +1523,7 @@ auto basic_enum(
14851523
{
14861524
std::string value{"-1"};
14871525

1488-
#line 957 "reflect.h2"
1526+
#line 991 "reflect.h2"
14891527
for (
14901528
auto const& m : CPP2_UFCS(get_members)(t) )
14911529
if ( CPP2_UFCS(is_member_object)(m))
@@ -1523,7 +1561,7 @@ std::string value{"-1"};
15231561
}
15241562
}
15251563

1526-
#line 993 "reflect.h2"
1564+
#line 1027 "reflect.h2"
15271565
if ((CPP2_UFCS(empty)(enumerators))) {
15281566
CPP2_UFCS(error)(t, "an enumeration must contain at least one enumerator value");
15291567
return ;
@@ -1569,7 +1607,7 @@ std::string value{"-1"};
15691607
}
15701608
}
15711609

1572-
#line 1039 "reflect.h2"
1610+
#line 1073 "reflect.h2"
15731611
// 2. Replace: Erase the contents and replace with modified contents
15741612
//
15751613
// Note that most values and functions are declared as '==' compile-time values, i.e. Cpp1 'constexpr'
@@ -1617,7 +1655,7 @@ std::string to_string{" to_string: (this) -> std::string = { \n"};
16171655

16181656
// Provide a 'to_string' function to print enumerator name(s)
16191657

1620-
#line 1084 "reflect.h2"
1658+
#line 1118 "reflect.h2"
16211659
{
16221660
if (bitwise) {
16231661
to_string += " _ret : std::string = \"(\";\n";
@@ -1649,10 +1687,10 @@ std::string to_string{" to_string: (this) -> std::string = { \n"};
16491687
CPP2_UFCS(add_member)(t, std::move(to_string));
16501688
}
16511689
}
1652-
#line 1114 "reflect.h2"
1690+
#line 1148 "reflect.h2"
16531691
}
16541692

1655-
#line 1126 "reflect.h2"
1693+
#line 1160 "reflect.h2"
16561694
auto cpp2_enum(meta::type_declaration& t) -> void
16571695
{
16581696
// Let basic_enum do its thing, with an incrementing value generator
@@ -1669,7 +1707,7 @@ auto cpp2_enum(meta::type_declaration& t) -> void
16691707
);
16701708
}
16711709

1672-
#line 1153 "reflect.h2"
1710+
#line 1187 "reflect.h2"
16731711
auto flag_enum(meta::type_declaration& t) -> void
16741712
{
16751713
// Let basic_enum do its thing, with a power-of-two value generator
@@ -1691,7 +1729,7 @@ auto flag_enum(meta::type_declaration& t) -> void
16911729
);
16921730
}
16931731

1694-
#line 1199 "reflect.h2"
1732+
#line 1233 "reflect.h2"
16951733
auto cpp2_union(meta::type_declaration& t) -> void
16961734
{
16971735
std::vector<value_member_info> alternatives {};
@@ -1700,7 +1738,7 @@ auto value{0};
17001738

17011739
// 1. Gather: All the user-written members, and find/compute the max size
17021740

1703-
#line 1206 "reflect.h2"
1741+
#line 1240 "reflect.h2"
17041742
for (
17051743

17061744
auto const& m : CPP2_UFCS(get_members)(t) ) { do
@@ -1725,7 +1763,7 @@ auto value{0};
17251763
} while (false); ++value; }
17261764
}
17271765

1728-
#line 1229 "reflect.h2"
1766+
#line 1263 "reflect.h2"
17291767
std::string discriminator_type {};
17301768
if (cpp2::cmp_less(CPP2_UFCS(ssize)(alternatives),std::numeric_limits<cpp2::i8>::max())) {
17311769
discriminator_type = "i8";
@@ -1740,7 +1778,7 @@ auto value{0};
17401778
discriminator_type = "i64";
17411779
}}}
17421780

1743-
#line 1244 "reflect.h2"
1781+
#line 1278 "reflect.h2"
17441782
// 2. Replace: Erase the contents and replace with modified contents
17451783

17461784
CPP2_UFCS(remove_marked_members)(t);
@@ -1749,40 +1787,40 @@ std::string storage{" _storage: cpp2::aligned_storage<cpp2::max( "};
17491787

17501788
// Provide storage
17511789

1752-
#line 1250 "reflect.h2"
1790+
#line 1284 "reflect.h2"
17531791
{
17541792
{
17551793
std::string comma{""};
17561794

1757-
#line 1252 "reflect.h2"
1795+
#line 1286 "reflect.h2"
17581796
for (
17591797

17601798
auto const& e : alternatives ) { do {
17611799
storage += comma + ("sizeof(" + cpp2::to_string(e.type) + ")");
17621800
} while (false); comma = ", "; }
17631801
}
17641802

1765-
#line 1258 "reflect.h2"
1803+
#line 1292 "reflect.h2"
17661804
storage += "), cpp2::max( ";
17671805
{
17681806
std::string comma{""};
17691807

1770-
#line 1261 "reflect.h2"
1808+
#line 1295 "reflect.h2"
17711809
for (
17721810

17731811
auto const& e : alternatives ) { do {
17741812
storage += comma + ("alignof(" + cpp2::to_string(e.type) + ")");
17751813
} while (false); comma = ", "; }
17761814
}
17771815

1778-
#line 1267 "reflect.h2"
1816+
#line 1301 "reflect.h2"
17791817
storage += " )> = ();\n";
17801818
CPP2_UFCS(add_member)(t, std::move(storage));
17811819
}
17821820
}
17831821

17841822
// Provide discriminator
1785-
#line 1272 "reflect.h2"
1823+
#line 1306 "reflect.h2"
17861824
CPP2_UFCS(add_member)(t, (" _discriminator: " + cpp2::to_string(std::move(discriminator_type)) + " = -1;\n"));
17871825

17881826
// Add the alternatives: is_alternative, get_alternative, and set_alternative
@@ -1804,7 +1842,7 @@ std::string destroy{" private _destroy: (inout this) = {\n"};
18041842

18051843
// Add destroy
18061844

1807-
#line 1291 "reflect.h2"
1845+
#line 1325 "reflect.h2"
18081846
{
18091847
for (
18101848
auto const& a : alternatives ) {
@@ -1818,7 +1856,7 @@ std::string destroy{" private _destroy: (inout this) = {\n"};
18181856
}
18191857

18201858
// Add the destructor
1821-
#line 1303 "reflect.h2"
1859+
#line 1337 "reflect.h2"
18221860
CPP2_UFCS(add_member)(t, " operator=: (move this) = { _destroy(); }");
18231861

18241862
// Add default constructor
@@ -1828,7 +1866,7 @@ std::string value_set{""};
18281866

18291867
// Add copy/move construction and assignment
18301868

1831-
#line 1310 "reflect.h2"
1869+
#line 1344 "reflect.h2"
18321870
{
18331871
for (
18341872
auto const& a : alternatives ) {
@@ -1848,16 +1886,16 @@ std::string value_set{""};
18481886
);
18491887
}
18501888
}
1851-
#line 1328 "reflect.h2"
1889+
#line 1362 "reflect.h2"
18521890
}
18531891

1854-
#line 1335 "reflect.h2"
1892+
#line 1369 "reflect.h2"
18551893
auto print(cpp2::in<meta::type_declaration> t) -> void
18561894
{
18571895
std::cout << CPP2_UFCS(print)(t) << "\n";
18581896
}
18591897

1860-
#line 1345 "reflect.h2"
1898+
#line 1379 "reflect.h2"
18611899
[[nodiscard]] auto apply_metafunctions(
18621900
declaration_node& n,
18631901
type_declaration& rtype,
@@ -1923,6 +1961,9 @@ auto print(cpp2::in<meta::type_declaration> t) -> void
19231961
else {if (name == "partially_ordered_value") {
19241962
partially_ordered_value(rtype);
19251963
}
1964+
else {if (name == "rule_of_zero") {
1965+
rule_of_zero(rtype);
1966+
}
19261967
else {if (name == "struct") {
19271968
cpp2_struct(rtype);
19281969
}
@@ -1940,9 +1981,9 @@ auto print(cpp2::in<meta::type_declaration> t) -> void
19401981
}
19411982
else {
19421983
error("unrecognized metafunction name: " + name);
1943-
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");
1984+
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");
19441985
return false;
1945-
}}}}}}}}}}}}}}}
1986+
}}}}}}}}}}}}}}}}
19461987

19471988
if ((
19481989
!(CPP2_UFCS(empty)(args))
@@ -1957,7 +1998,7 @@ auto print(cpp2::in<meta::type_declaration> t) -> void
19571998
return true;
19581999
}
19592000

1960-
#line 1445 "reflect.h2"
2001+
#line 1482 "reflect.h2"
19612002
}
19622003

19632004
}

0 commit comments

Comments
 (0)