My goal here is to sit the semantic values in modern C++ on top of union, instead of a char buffer. To this end, I need the buffer-model and union one to be comparable, and there is nothing corresponding to variant<S> in the union model (which is specific to the actual union members, not parameterized).
commit e76a9348536b5926d9b7c8caaa880bd2abccdac3 Author: Akim Demaille <[email protected]> Date: Sat Dec 1 18:27:41 2018 +0100 c++: don't define variant<S>, directly define semantic_type Instead of defining yy::variant<S> and then alias yy::parser::semantic_type to variant<sizeof (union_type)>, directly define yy::parser::semantic_type. This model is more appropriate if we want to sit the storage on top of unions in C++11. * data/variant.hh (b4_variant_define): Specialize and inline the definition into... (b4_value_type_declare): Here. Define union_type here. * data/lalr1.cc: Adjust. diff --git a/data/lalr1.cc b/data/lalr1.cc index 89ebdcbc..322971bf 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -178,8 +178,6 @@ m4_define([b4_shared_declarations], ]b4_bison_locations_if([m4_ifndef([b4_location_file], [b4_location_define])])[ -]b4_variant_if([b4_variant_define])[ - /// A Bison parser. class ]b4_parser_class_name[ { diff --git a/data/variant.hh b/data/variant.hh index 8a340f1a..93ee3218 100644 --- a/data/variant.hh +++ b/data/variant.hh @@ -78,38 +78,45 @@ m4_define([b4_variant_includes], #endif ]]) -# b4_variant_define -# ----------------- -# Define "variant". -m4_define([b4_variant_define], -[[ /// A char[S] buffer to store and retrieve objects. + + +## -------------------------- ## +## Adjustments for variants. ## +## -------------------------- ## + + +# b4_value_type_declare +# --------------------- +# Declare semantic_type. +m4_define([b4_value_type_declare], +[[ /// A buffer to store and retrieve objects. /// /// Sort of a variant, but does not keep track of the nature /// of the stored data, since that knowledge is available - /// via the current state. - template <size_t S> - struct variant + /// via the current parser state. + class semantic_type { + public: /// Type of *this. - typedef variant<S> self_type; + typedef semantic_type self_type; /// Empty construction. - variant () YY_NOEXCEPT + semantic_type () YY_NOEXCEPT : yybuffer_ ()]b4_parse_assert_if([ , yytypeid_ (YY_NULLPTR)])[ {} /// Construct and fill. template <typename T> - variant (YY_RVREF (T) t)]b4_parse_assert_if([ + semantic_type (YY_RVREF (T) t)]b4_parse_assert_if([ : yytypeid_ (&typeid (T))])[ { - YYASSERT (sizeof (T) <= S); + YYASSERT (sizeof (T) <= size); new (yyas_<T> ()) T (YY_MOVE (t)); } /// Destruction, allowed only if empty. - ~variant () YY_NOEXCEPT + ~semantic_type () YY_NOEXCEPT {]b4_parse_assert_if([ YYASSERT (!yytypeid_); ])[} @@ -120,7 +127,7 @@ m4_define([b4_variant_define], emplace () {]b4_parse_assert_if([ YYASSERT (!yytypeid_); - YYASSERT (sizeof (T) <= S); + YYASSERT (sizeof (T) <= size); yytypeid_ = & typeid (T);])[ return *new (yyas_<T> ()) T (); } @@ -132,7 +139,7 @@ m4_define([b4_variant_define], emplace (U&& u) {]b4_parse_assert_if([ YYASSERT (!yytypeid_); - YYASSERT (sizeof (T) <= S); + YYASSERT (sizeof (T) <= size); yytypeid_ = & typeid (T);])[ return *new (yyas_<T> ()) T (std::forward <U>(u)); } @@ -143,7 +150,7 @@ m4_define([b4_variant_define], emplace (const T& t) {]b4_parse_assert_if([ YYASSERT (!yytypeid_); - YYASSERT (sizeof (T) <= S); + YYASSERT (sizeof (T) <= size); yytypeid_ = & typeid (T);])[ return *new (yyas_<T> ()) T (t); } @@ -174,7 +181,7 @@ m4_define([b4_variant_define], {]b4_parse_assert_if([ YYASSERT (yytypeid_); YYASSERT (*yytypeid_ == typeid (T)); - YYASSERT (sizeof (T) <= S);])[ + YYASSERT (sizeof (T) <= size);])[ return *yyas_<T> (); } @@ -185,7 +192,7 @@ m4_define([b4_variant_define], {]b4_parse_assert_if([ YYASSERT (yytypeid_); YYASSERT (*yytypeid_ == typeid (T)); - YYASSERT (sizeof (T) <= S);])[ + YYASSERT (sizeof (T) <= size);])[ return *yyas_<T> (); } @@ -196,7 +203,7 @@ m4_define([b4_variant_define], /// unconstructed variants: it would require some dynamic testing, which /// should not be the variant's responsibility. /// Swapping between built and (possibly) non-built is done with - /// variant::move (). + /// self_type::move (). template <typename T> void swap (self_type& other) YY_NOEXCEPT @@ -253,7 +260,7 @@ m4_define([b4_variant_define], private: /// Prohibit blind copies. self_type& operator= (const self_type&); - variant (const self_type&); + semantic_type (const self_type&); /// Accessor to raw memory as \a T. template <typename T> @@ -273,12 +280,20 @@ m4_define([b4_variant_define], return static_cast<const T*> (yyp); } + /// An auxiliary type to compute the largest semantic type. + union union_type + {]b4_type_foreach([b4_char_sizeof])[ }; + + /// The size of the largest semantic type. + enum { size = sizeof (union_type) }; + + /// A buffer to store semantic values. union { /// Strongest alignment constraints. long double yyalign_me; /// A buffer large enough to store any of the semantic values. - char yyraw[S]; + char yyraw[size]; } yybuffer_;]b4_parse_assert_if([ /// Whether the content is built: if defined, the name of the stored type. @@ -287,24 +302,6 @@ m4_define([b4_variant_define], ]]) -## -------------------------- ## -## Adjustments for variants. ## -## -------------------------- ## - - -# b4_value_type_declare -# --------------------- -# Declare semantic_type. -m4_define([b4_value_type_declare], -[[ /// An auxiliary type to compute the largest semantic type. - union union_type - {]b4_type_foreach([b4_char_sizeof])[}; - - /// Symbol semantic values. - typedef variant<sizeof (union_type)> semantic_type;][]dnl -]) - - # How the semantic value is extracted when using variants. # b4_symbol_value(VAL, [TYPE])
