@@ -38,7 +38,7 @@ class alias_declaration;
38
38
#line 807 "reflect.h2"
39
39
class value_member_info ;
40
40
41
- #line 1030 "reflect.h2"
41
+ #line 1115 "reflect.h2"
42
42
}
43
43
}
44
44
@@ -627,7 +627,7 @@ struct basic_enum__ret { std::string underlying_type; std::string strict_underly
627
627
cpp2::in<bool > bitwise
628
628
) -> basic_enum__ret;
629
629
630
- #line 967 "reflect.h2"
630
+ #line 974 "reflect.h2"
631
631
// -----------------------------------------------------------------------
632
632
//
633
633
// "An enum[...] is a totally ordered value type that stores a
@@ -639,7 +639,7 @@ struct basic_enum__ret { std::string underlying_type; std::string strict_underly
639
639
//
640
640
auto cpp2_enum (meta::type_declaration& t) -> void;
641
641
642
- #line 992 "reflect.h2"
642
+ #line 999 "reflect.h2"
643
643
// -----------------------------------------------------------------------
644
644
//
645
645
// "flag_enum expresses an enumeration that stores values
@@ -652,8 +652,34 @@ auto cpp2_enum(meta::type_declaration& t) -> void;
652
652
//
653
653
auto flag_enum (meta::type_declaration& t) -> void;
654
654
655
- #line 1027 "reflect.h2"
655
+ #line 1034 "reflect.h2"
656
+ // -----------------------------------------------------------------------
657
+ //
658
+ // "As with void*, programmers should know that unions [...] are
659
+ // inherently dangerous, should be avoided wherever possible,
660
+ // and should be handled with special care when actually needed."
661
+ //
662
+ // -- Stroustrup (The Design and Evolution of C++, 14.3.4.1)
663
+ //
664
+ // "C++17 needs a type-safe union... The implications of the
665
+ // consensus `variant` design are well understood and have been
666
+ // explored over several LEWG discussions, over a thousand emails,
667
+ // a joint LEWG/EWG session, and not to mention 12 years of
668
+ // experience with Boost and other libraries."
669
+ //
670
+ // -- Axel Naumann, in P0088 (wg21.link/p0088),
671
+ // the adopted proposal for C++17 std::variant
672
+ //
673
+ // -----------------------------------------------------------------------
674
+ //
675
+ // union
676
+ //
677
+ // a type that contains exactly one of a fixed set of values at a time
656
678
//
679
+
680
+ auto cpp2_union (meta::type_declaration& t) -> void;
681
+
682
+ #line 1113 "reflect.h2"
657
683
// =======================================================================
658
684
// Switch to Cpp1 and close subnamespace meta
659
685
}
@@ -722,8 +748,11 @@ auto parser::apply_type_meta_functions( declaration_node& n )
722
748
else if (name == " flag_enum" ) {
723
749
flag_enum ( rtype );
724
750
}
751
+ else if (name == " union" ) {
752
+ cpp2_union ( rtype );
753
+ }
725
754
else {
726
- error ( " (temporary alpha limitation) unrecognized metafunction name '" + name + " ' - 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" );
755
+ error ( " (temporary alpha limitation) unrecognized metafunction name '" + name + " ' - 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 " );
727
756
return false ;
728
757
}
729
758
}
@@ -1442,16 +1471,23 @@ cpp2::i64 value = -1;
1442
1471
to_string += " ret: std::string = ();\n " ;
1443
1472
auto first {true };
1444
1473
1474
+ if (bitwise) {
1475
+ to_string += " comma: std::string = ();\n " ;
1476
+ }
1477
+
1445
1478
for (
1446
1479
1447
1480
auto const & e : enumerators ) { do {
1448
1481
if (bitwise) {
1449
- std::string comma {" std::string(\" , \" ) + " };
1450
1482
if (first) {
1451
1483
to_string += " ret = \" (\" ;\n " ;
1452
- comma = " " ;
1453
1484
}
1454
- to_string += " if value & (" + cpp2::to_string (e.name ) + " ) { ret += " + cpp2::to_string (comma) + " \" " + cpp2::to_string (e.name ) + " \" ; }\n " ;
1485
+ if (e.name == " none" ) { // a "none" flag should match if no bits set
1486
+ to_string += " if value == " + cpp2::to_string (e.name ) + " { ret += comma + \" " + cpp2::to_string (e.name ) + " \" ; comma = \" , \" ; }\n " ;
1487
+ }
1488
+ else { // other flags need to be &-ed
1489
+ to_string += " if (value & " + cpp2::to_string (e.name ) + " ) == " + cpp2::to_string (e.name ) + " { ret += comma + \" " + cpp2::to_string (e.name ) + " \" ; comma = \" , \" ; }\n " ;
1490
+ }
1455
1491
}
1456
1492
else {
1457
1493
std::string else_ {" else " };
@@ -1477,13 +1513,13 @@ cpp2::i64 value = -1;
1477
1513
CPP2_UFCS (require, t, CPP2_UFCS (add_member, t, " to_string: (this) -> std::string = { return " + cpp2::to_string (CPP2_UFCS_0 (name, t)) + " ::to_string(this); }" ),
1478
1514
" could not add to_string member function" );
1479
1515
1480
- #line 961 "reflect.h2"
1516
+ #line 968 "reflect.h2"
1481
1517
// 3. A basic_enum is-a value type
1482
1518
1483
1519
CPP2_UFCS_0 (basic_value, t);
1484
1520
return { std::move (underlying_type), std::move (strict_underlying_type.value ()) }; }
1485
1521
1486
- #line 976 "reflect.h2"
1522
+ #line 983 "reflect.h2"
1487
1523
auto cpp2_enum (meta::type_declaration& t) -> void
1488
1524
{
1489
1525
// Let basic_enum do its thing, with an incrementing value generator
@@ -1499,7 +1535,7 @@ auto cpp2_enum(meta::type_declaration& t) -> void
1499
1535
));
1500
1536
}
1501
1537
1502
- #line 1002 "reflect.h2"
1538
+ #line 1009 "reflect.h2"
1503
1539
auto flag_enum (meta::type_declaration& t) -> void
1504
1540
{
1505
1541
// Add "none" member as a regular name to signify "no flags set"
@@ -1524,7 +1560,63 @@ auto flag_enum(meta::type_declaration& t) -> void
1524
1560
));
1525
1561
}
1526
1562
1527
- #line 1030 "reflect.h2"
1563
+ #line 1058 "reflect.h2"
1564
+ auto cpp2_union (meta::type_declaration& t) -> void
1565
+ {
1566
+ std::vector<value_member_info> alternatives {};
1567
+
1568
+ // 1. Gather: All the user-written members, and find/compute the max size
1569
+
1570
+ // (copy first := true)
1571
+ for (
1572
+ // next first = false
1573
+ auto const & m : CPP2_UFCS_0 (get_members, t) )
1574
+ {
1575
+ CPP2_UFCS (require, m, (CPP2_UFCS_0 (is_public, m) || CPP2_UFCS_0 (is_default_access, m)) && CPP2_UFCS_0 (is_object, m),
1576
+ " a union alternative cannot be protected or private" );
1577
+
1578
+ if (CPP2_UFCS_0 (is_object, m)) {
1579
+ auto mo {CPP2_UFCS_0 (as_object, m)};
1580
+
1581
+ // Adding local variable 'e' to work around a Clang warning
1582
+ value_member_info e {cpp2::as_<std::string>(CPP2_UFCS_0 (name, mo)), CPP2_UFCS_0 (type, mo), cpp2::as_<std::string>(CPP2_UFCS_0 (initializer, mo))};
1583
+ CPP2_UFCS (push_back, alternatives, e);
1584
+ }
1585
+ }
1586
+
1587
+ #line 1082 "reflect.h2"
1588
+ // 2. Replace: Erase the contents and replace with modified contents
1589
+
1590
+ CPP2_UFCS_0 (remove_all_members, t);
1591
+
1592
+ // Compute the size
1593
+ std::string Size {" Size :== cpp2::max( " };
1594
+ {
1595
+ std::string comma = " " ;
1596
+
1597
+ #line 1090 "reflect.h2"
1598
+ for (
1599
+
1600
+ auto const & e : alternatives ) { do {
1601
+ Size += comma + " sizeof(" + cpp2::to_string (e.type ) + " )" ;
1602
+ } while (false ); comma = " , " ; }
1603
+ }
1604
+
1605
+ #line 1096 "reflect.h2"
1606
+ Size += " );\n " ;
1607
+ CPP2_UFCS (require, t, CPP2_UFCS (add_member, t, std::move (Size )),
1608
+ " could not add Size" );
1609
+
1610
+ #line 1102 "reflect.h2"
1611
+ // TODO
1612
+
1613
+ #line 1106 "reflect.h2"
1614
+ // // 3. A basic_enum is-a value
1615
+
1616
+ // t.value();
1617
+ }
1618
+
1619
+ #line 1115 "reflect.h2"
1528
1620
}
1529
1621
}
1530
1622
0 commit comments