diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2013-10-15 07:01:17 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2013-10-15 07:01:17 +0200 |
commit | a482f1c4dd4efab83d3b19309900f1cbf54383a5 (patch) | |
tree | 3c1ab27e420cbf760a54a1c4be61bbd0448a4873 | |
parent | 400d258aab3722be3a4b8548870afad1574f3ad8 (diff) |
Automatically map C++11 enum classes (strong enums)
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | doc/manual.xhtml | 138 | ||||
-rw-r--r-- | odb/context.cxx | 15 | ||||
-rw-r--r-- | odb/parser.cxx | 39 | ||||
-rw-r--r-- | odb/relational/mssql/context.cxx | 9 | ||||
-rw-r--r-- | odb/relational/mysql/context.cxx | 59 | ||||
-rw-r--r-- | odb/relational/oracle/context.cxx | 9 | ||||
-rw-r--r-- | odb/relational/pgsql/context.cxx | 9 | ||||
-rw-r--r-- | odb/relational/sqlite/context.cxx | 9 | ||||
-rw-r--r-- | odb/semantics/elements.hxx | 7 | ||||
-rw-r--r-- | odb/semantics/enum.cxx | 21 | ||||
-rw-r--r-- | odb/semantics/enum.hxx | 90 | ||||
-rw-r--r-- | odb/semantics/fundamental.cxx | 68 | ||||
-rw-r--r-- | odb/semantics/fundamental.hxx | 61 | ||||
-rw-r--r-- | odb/traversal/enum.cxx | 21 | ||||
-rw-r--r-- | odb/traversal/enum.hxx | 23 |
16 files changed, 439 insertions, 143 deletions
@@ -10,6 +10,10 @@ Version 2.3.0 to Chapter 9, "Sections" in the ODB manual as well as the 'section' example in the odb-examples package. + * Support for automatic mapping of C++11 enum classes in addition to the + "old" enums. For more information, refer to the ODB manual "Type Mapping" + sections for each database system. + * Support for pattern matching (SQL LIKE operator) in the C++-integrated queries. For more information, refer to Section 4.1, "ODB Query Language" in the ODB manual. diff --git a/doc/manual.xhtml b/doc/manual.xhtml index 79722db..9537121 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -15809,10 +15809,11 @@ class person <p>Default values specified as enumerators are only supported for members that are mapped to an <code>ENUM</code> or an integer type in the database, which is the case for the automatic - mapping of C++ enums to suitable database types as performed - by the ODB compiler. If you have mapped a C++ enum to another - database type, then you should use a literal corresponding - to that type to specify the default value. For example:</p> + mapping of C++ enums and enum classes to suitable database + types as performed by the ODB compiler. If you have mapped + a C++ enum or enum class to another database type, then you + should use a literal corresponding to that type to specify + the default value. For example:</p> <pre class="cxx"> enum gender {male, female, undisclosed}; @@ -18670,16 +18671,18 @@ person.hxx to the <code>VARCHAR(255)</code> MySQL type. Otherwise, it is mapped to <code>TEXT</code>.</p> - <p>Additionally, by default, C++ enumerations are automatically - mapped to a suitable MySQL type. Contiguous enumerations with - the zero first enumerator are mapped to the MySQL <code>ENUM</code> - type. All other enumerations are mapped to <code>INT</code> or - <code>INT UNSIGNED</code>. In both cases the default <code>NULL</code> - semantics is <code>NOT NULL</code>. For example:</p> + <p>Additionally, by default, C++ enums and C++11 enum classes are + automatically mapped to suitable MySQL types. Contiguous + enumerations with the zero first enumerator are mapped to + the MySQL <code>ENUM</code> type. All other enumerations + are mapped to the MySQL types corresponding to their + underlying integral types (see table above). In both + cases the default <code>NULL</code> semantics is + <code>NOT NULL</code>. For example:</p> <pre class="cxx"> enum color {red, green, blue}; -enum taste +enum class taste: unsigned char { bitter = 1, // Non-zero first enumerator. sweet, @@ -18693,7 +18696,7 @@ class object ... color color_; // Mapped to ENUM ('red', 'green', 'blue') NOT NULL. - taste taste_; // Mapped to INT UNSIGNED NOT NULL. + taste taste_; // Mapped to TINYNT UNSIGNED NOT NULL. }; </pre> @@ -19433,9 +19436,30 @@ class object <code>db not_null</code> pragma (<a href="#14.4.6">Section 14.4.6, "<code>null/not_null</code>"</a>).</p> - <p>Additionally, by default, C++ enumerations are automatically mapped to - the SQLite <code>INTEGER</code> type with the default <code>NULL</code> - semantics being <code>NOT NULL</code>.</p> + <p>Additionally, by default, C++ enums and C++11 enum classes are + automatically mapped to the SQLite <code>INTEGER</code> type with + the default <code>NULL</code> semantics being <code>NOT NULL</code>. + For example:</p> + + <pre class="cxx"> +enum color {red, green, blue}; +enum class taste: unsigned char +{ + bitter = 1, + sweet, + sour = 4, + salty +}; + +#pragma db object +class object +{ + ... + + color color_; // Automatically mapped to INTEGER. + taste taste_; // Automatically mapped to INTEGER. +}; + </pre> <p>Note also that SQLite only operates with signed integers and the largest value that an SQLite database can store is a signed 64-bit integer. As @@ -20406,9 +20430,31 @@ class object <code>db type</code> pragma (<a href="#14.4.3">Section 14.4.3, "<code>type</code>"</a>).</p> - <p>Additionally, by default, C++ enumerations are automatically - mapped to <code>INTEGER</code> with the default <code>NULL</code> - semantics being <code>NOT NULL</code>.</p> + <p>Additionally, by default, C++ enums and C++11 enum classes are + automatically mapped to the PostgreSQL types corresponding to their + underlying integral types (see table above). The default + <code>NULL</code> semantics is <code>NOT NULL</code>. For + example:</p> + + <pre class="cxx"> +enum color {red, green, blue}; +enum class taste: unsigned char +{ + bitter = 1, + sweet, + sour = 4, + salty +}; + +#pragma db object +class object +{ + ... + + color color_; // Automatically mapped to INTEGER. + taste taste_; // Automatically mapped to SMALLINT. +}; + </pre> <p>Note also that because PostgreSQL does not support unsigned integers, the <code>unsigned short</code>, <code>unsigned int</code>, and @@ -21174,9 +21220,31 @@ class object object ids that are mapped to these Oracle types, an empty string is an invalid value.</p> - <p>Additionally, by default, C++ enumerations are automatically - mapped to <code>NUMBER(10)</code> with the default <code>NULL</code> - semantics being <code>NOT NULL</code>.</p> + <p>Additionally, by default, C++ enums and C++11 enum classes are + automatically mapped to the Oracle types corresponding to their + underlying integral types (see table above). The default + <code>NULL</code> semantics is <code>NOT NULL</code>. For + example:</p> + + <pre class="cxx"> +enum color {red, green, blue}; +enum class taste: unsigned char +{ + bitter = 1, + sweet, + sour = 4, + salty +}; + +#pragma db object +class object +{ + ... + + color color_; // Automatically mapped to NUMBER(10). + taste taste_; // Automatically mapped to NUMBER(3). +}; + </pre> <p>It is also possible to add support for additional Oracle types, such as <code>XML</code>, geospatial types, user-defined types, @@ -22114,9 +22182,31 @@ class object always change this mapping using the <code>db type</code> pragma (<a href="#14.4.3">Section 14.4.3, "<code>type</code>"</a>).</p> - <p>Additionally, by default, C++ enumerations are automatically - mapped to <code>INT</code> with the default <code>NULL</code> - semantics being <code>NOT NULL</code>.</p> + <p>Additionally, by default, C++ enums and C++11 enum classes are + automatically mapped to the SQL Server types corresponding to their + underlying integral types (see table above). The default + <code>NULL</code> semantics is <code>NOT NULL</code>. For + example:</p> + + <pre class="cxx"> +enum color {red, green, blue}; +enum class taste: unsigned char +{ + bitter = 1, + sweet, + sour = 4, + salty +}; + +#pragma db object +class object +{ + ... + + color color_; // Automatically mapped to INT. + taste taste_; // Automatically mapped to TINYINT. +}; + </pre> <p>Note also that because SQL Server does not support unsigned integers, the <code>unsigned short</code>, <code>unsigned int</code>, and diff --git a/odb/context.cxx b/odb/context.cxx index 4db15a0..352cb51 100644 --- a/odb/context.cxx +++ b/odb/context.cxx @@ -1926,16 +1926,25 @@ database_type_impl (semantics::type& t, bool id, bool* null) { - type_map_type::const_iterator i (data_->type_map_.find (t, hint)); + using semantics::enum_; + + // By default map an enum as its underlying type. + // + if (enum_* e = dynamic_cast<enum_*> (&t)) + return database_type_impl ( + e->underlying_type (), e->underlying_type_hint (), id, null); + // Built-in type mapping. + // + type_map_type::const_iterator i (data_->type_map_.find (t, hint)); if (i != data_->type_map_.end ()) { if (null != 0) *null = i->second.null; return id ? i->second.id_type : i->second.type; } - else - return string (); + + return string (); } static string diff --git a/odb/parser.cxx b/odb/parser.cxx index 14dd81a..140e09e 100644 --- a/odb/parser.cxx +++ b/odb/parser.cxx @@ -746,7 +746,7 @@ parse (tree global_scope, path const& main_file) define_fund<fund_char> (char_type_node); define_fund<fund_wchar> (wchar_type_node); - if (ops_.std () == cxx_version::cxx11) + if (ops_.std () >= cxx_version::cxx11) { define_fund<fund_char16> (char16_type_node); define_fund<fund_char32> (char32_type_node); @@ -1422,8 +1422,29 @@ emit_enum (tree e, e_node = &dynamic_cast<enum_&> (*n); else { - e_node = &unit_->new_node<enum_> ( - file, line, clmn, e, TYPE_UNSIGNED (e) != 0); + e_node = &unit_->new_node<enum_> (file, line, clmn, e); + + // Set the underlying type even for incomplete (forward-declared) enums. + // + tree ut (ENUM_UNDERLYING_TYPE (e)); + names* hint (unit_->find_hint (ut)); + integral_type* un = dynamic_cast<integral_type*> ( + unit_->find (TYPE_MAIN_VARIANT (ut))); + + // For "old" enums GCC creates a distinct type node and the only way to + // get to one of the known integrals is via its name. + // + if (un == 0) + { + ut = TREE_TYPE (TYPE_NAME (ut)); + un = dynamic_cast<integral_type*> (unit_->find (TYPE_MAIN_VARIANT (ut))); + } + + underlies& edge (unit_->new_edge<underlies> (*un, *e_node)); + + if (hint != 0) + edge.hint (*hint); + unit_->insert (e, *e_node); } @@ -1459,9 +1480,17 @@ emit_enum (tree e, unit_->new_edge<enumerates> (*e_node, er_node); unit_->insert (decl, er_node); - // Inject enumerators into the outer scope. + // In C++11 the enumerators are always available in the enum's + // scope, even for old enums. + // + if (ops_.std () >= cxx_version::cxx11) + unit_->new_edge<names> (*e_node, er_node, name, access::public_); + + // Inject enumerators into the outer scope unless this is an + // enum class. // - unit_->new_edge<names> (*scope_, er_node, name, access); + if (UNSCOPED_ENUM_P (e)) + unit_->new_edge<names> (*scope_, er_node, name, access); if (trace) ts << "\tenumerator " << name << " at " << file << ":" << line << endl; diff --git a/odb/relational/mssql/context.cxx b/odb/relational/mssql/context.cxx index 1df235d..a0037eb 100644 --- a/odb/relational/mssql/context.cxx +++ b/odb/relational/mssql/context.cxx @@ -156,18 +156,11 @@ namespace relational if (!r.empty ()) return r; - using semantics::enum_; using semantics::array; - // Enum mapping. - // - if (t.is_a<semantics::enum_> ()) - { - r = "INT"; - } // char[N] mapping. // - else if (array* a = dynamic_cast<array*> (&t)) + if (array* a = dynamic_cast<array*> (&t)) { semantics::type& bt (a->base_type ()); bool c (bt.is_a<semantics::fund_char> ()); diff --git a/odb/relational/mysql/context.cxx b/odb/relational/mysql/context.cxx index 75b71e9..55dd4f7 100644 --- a/odb/relational/mysql/context.cxx +++ b/odb/relational/mysql/context.cxx @@ -286,15 +286,12 @@ namespace relational bool id, bool* null) { - string r (base_context::database_type_impl (t, hint, id, null)); - - if (!r.empty ()) - return r; - using semantics::enum_; using semantics::enumerator; using semantics::array; + string r; + // Enum mapping. // if (enum_* e = dynamic_cast<enum_*> (&t)) @@ -302,43 +299,41 @@ namespace relational // We can only map to ENUM if the C++ enumeration is contiguous // and starts with 0. // - if (e->unsigned_ ()) + enum_::enumerates_iterator i (e->enumerates_begin ()), + end (e->enumerates_end ()); + + if (i != end) { - enum_::enumerates_iterator i (e->enumerates_begin ()), - end (e->enumerates_end ()); + r += "ENUM("; - if (i != end) + for (unsigned long long j (0); i != end; ++i, ++j) { - r += "ENUM("; - - for (unsigned long long j (0); i != end; ++i, ++j) - { - enumerator const& er (i->enumerator ()); + enumerator const& er (i->enumerator ()); - if (er.value () != j) - break; - - if (j != 0) - r += ", "; + if (er.value () != j) + break; - r += quote_string (er.name ()); - } + if (j != 0) + r += ", "; - if (i == end) - r += ")"; - else - r.clear (); + r += quote_string (er.name ()); } - } - - if (r.empty ()) - { - r = "INT"; - if (e->unsigned_ ()) - r += " UNSIGNED"; + if (i == end) + r += ")"; + else + r.clear (); } + + if (!r.empty ()) + return r; } + + r = base_context::database_type_impl (t, hint, id, null); + + if (!r.empty ()) + return r; + // char[N] mapping. // else if (array* a = dynamic_cast<array*> (&t)) diff --git a/odb/relational/oracle/context.cxx b/odb/relational/oracle/context.cxx index f885564..98cda52 100644 --- a/odb/relational/oracle/context.cxx +++ b/odb/relational/oracle/context.cxx @@ -152,18 +152,11 @@ namespace relational if (!r.empty ()) return r; - using semantics::enum_; using semantics::array; - // Enum mapping. - // - if (t.is_a<semantics::enum_> ()) - { - r = "NUMBER(10)"; - } // char[N] mapping. // - else if (array* a = dynamic_cast<array*> (&t)) + if (array* a = dynamic_cast<array*> (&t)) { semantics::type& bt (a->base_type ()); if (bt.is_a<semantics::fund_char> ()) diff --git a/odb/relational/pgsql/context.cxx b/odb/relational/pgsql/context.cxx index 947c6bd..d09fa2c 100644 --- a/odb/relational/pgsql/context.cxx +++ b/odb/relational/pgsql/context.cxx @@ -252,18 +252,11 @@ namespace relational if (!r.empty ()) return r; - using semantics::enum_; using semantics::array; - // Enum mapping. - // - if (t.is_a<semantics::enum_> ()) - { - r = "INTEGER"; - } // char[N] mapping. // - else if (array* a = dynamic_cast<array*> (&t)) + if (array* a = dynamic_cast<array*> (&t)) { semantics::type& bt (a->base_type ()); if (bt.is_a<semantics::fund_char> ()) diff --git a/odb/relational/sqlite/context.cxx b/odb/relational/sqlite/context.cxx index 664af35..f347d30 100644 --- a/odb/relational/sqlite/context.cxx +++ b/odb/relational/sqlite/context.cxx @@ -242,18 +242,11 @@ namespace relational if (!r.empty ()) return r; - using semantics::enum_; using semantics::array; - // Enum mapping. - // - if (t.is_a<semantics::enum_> ()) - { - r = "INTEGER"; - } // char[N] mapping. // - else if (array* a = dynamic_cast<array*> (&t)) + if (array* a = dynamic_cast<array*> (&t)) { semantics::type& bt (a->base_type ()); if (bt.is_a<semantics::fund_char> () || diff --git a/odb/semantics/elements.hxx b/odb/semantics/elements.hxx index 1199c0c..059b639 100644 --- a/odb/semantics/elements.hxx +++ b/odb/semantics/elements.hxx @@ -178,9 +178,10 @@ namespace semantics // edges. // void - add_edge_right (edge&) - { - } + add_edge_left (edge&) {} + + void + add_edge_right (edge&) {} protected: // For virtual inheritance. Should never be actually called. diff --git a/odb/semantics/enum.cxx b/odb/semantics/enum.cxx index 7cffe30..dd8b905 100644 --- a/odb/semantics/enum.cxx +++ b/odb/semantics/enum.cxx @@ -22,13 +22,18 @@ namespace semantics { } + underlies:: + underlies () + : type_ (0), enum__ (0), hint_ (0) + { + } + enum_:: enum_ (path const& file, size_t line, size_t column, - tree tn, - bool unsigned_) - : node (file, line, column, tn), unsigned__ (unsigned_) + tree tn) + : node (file, line, column, tn) { } @@ -54,15 +59,25 @@ namespace semantics // { type_info ti (typeid (enumerator)); + ti.add_base (typeid (nameable)); ti.add_base (typeid (instance)); insert (ti); } + // underlies + // + { + type_info ti (typeid (underlies)); + ti.add_base (typeid (edge)); + insert (ti); + } + // enum_ // { type_info ti (typeid (enum_)); ti.add_base (typeid (type)); + ti.add_base (typeid (scope)); insert (ti); } } diff --git a/odb/semantics/enum.hxx b/odb/semantics/enum.hxx index de07885..02f2b27 100644 --- a/odb/semantics/enum.hxx +++ b/odb/semantics/enum.hxx @@ -7,6 +7,7 @@ #include <vector> #include <odb/semantics/elements.hxx> +#include <odb/semantics/fundamental.hxx> namespace semantics { @@ -101,7 +102,62 @@ namespace semantics // // - class enum_: public type + class underlies: public edge + { + public: + typedef semantics::enum_ enum_type; + + integral_type& + type () const + { + return *type_; + } + + enum_type& + enum_ () const + { + return *enum__; + } + + // Names edge in terms of which this edge was defined. Can be NULL. + // + public: + void + hint (names& hint) + { + hint_ = &hint; + } + + names* + hint () const + { + return hint_; + } + + public: + underlies (); + + void + set_left_node (integral_type& n) + { + type_ = &n; + } + + void + set_right_node (enum_type& n) + { + enum__ = &n; + } + + protected: + integral_type* type_; + enum_type* enum__; + names* hint_; + }; + + // + // + class enum_: public type, public scope { private: typedef std::vector<enumerates*> enumerates_list; @@ -123,14 +179,38 @@ namespace semantics return enumerates_.end (); } + underlies& + underlied () const + { + return *underlied_; + } + + integral_type& + underlying_type () const + { + return underlied_->type (); + } + + names* + underlying_type_hint () const + { + return underlied_->hint (); + } + bool unsigned_ () const { - return unsigned__; + return underlying_type ().unsigned_ (); } public: - enum_ (path const&, size_t line, size_t column, tree, bool unsigned_); + enum_ (path const&, size_t line, size_t column, tree); + + void + add_edge_right (underlies& e) + { + underlied_ = &e; + } void add_edge_left (enumerates& e) @@ -138,9 +218,11 @@ namespace semantics enumerates_.push_back (&e); } + using scope::add_edge_left; + private: - bool unsigned__; enumerates_list enumerates_; + underlies* underlied_; }; } diff --git a/odb/semantics/fundamental.cxx b/odb/semantics/fundamental.cxx index 537a5cf..4a3bd69 100644 --- a/odb/semantics/fundamental.cxx +++ b/odb/semantics/fundamental.cxx @@ -2,6 +2,8 @@ // copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC // license : GNU GPL v3; see accompanying LICENSE file +#include <odb/gcc.hxx> + #include <cutl/compiler/type-info.hxx> #include <odb/semantics/fundamental.hxx> @@ -22,6 +24,22 @@ namespace semantics return type::fq_name (hint); } + // char + // + bool fund_char:: + unsigned_ () const + { + return TYPE_UNSIGNED (tree_node ()) != 0; + } + + // wchar_t + // + bool fund_wchar:: + unsigned_ () const + { + return TYPE_UNSIGNED (tree_node ()) != 0; + } + // type info // namespace @@ -48,11 +66,19 @@ namespace semantics insert (ti); } + // integral_type + // + { + type_info ti (typeid (integral_type)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + // fund_bool // { type_info ti (typeid (fund_bool)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -60,7 +86,7 @@ namespace semantics // { type_info ti (typeid (fund_char)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -68,7 +94,23 @@ namespace semantics // { type_info ti (typeid (fund_wchar)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); + insert (ti); + } + + // fund_char16 + // + { + type_info ti (typeid (fund_char16)); + ti.add_base (typeid (integral_type)); + insert (ti); + } + + // fund_char32 + // + { + type_info ti (typeid (fund_char32)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -76,7 +118,7 @@ namespace semantics // { type_info ti (typeid (fund_signed_char)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -84,7 +126,7 @@ namespace semantics // { type_info ti (typeid (fund_unsigned_char)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -92,7 +134,7 @@ namespace semantics // { type_info ti (typeid (fund_short)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -100,7 +142,7 @@ namespace semantics // { type_info ti (typeid (fund_unsigned_short)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -108,7 +150,7 @@ namespace semantics // { type_info ti (typeid (fund_int)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -116,7 +158,7 @@ namespace semantics // { type_info ti (typeid (fund_unsigned_int)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -124,7 +166,7 @@ namespace semantics // { type_info ti (typeid (fund_long)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -132,7 +174,7 @@ namespace semantics // { type_info ti (typeid (fund_unsigned_long)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -140,7 +182,7 @@ namespace semantics // { type_info ti (typeid (fund_long_long)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } @@ -148,7 +190,7 @@ namespace semantics // { type_info ti (typeid (fund_unsigned_long_long)); - ti.add_base (typeid (fund_type)); + ti.add_base (typeid (integral_type)); insert (ti); } diff --git a/odb/semantics/fundamental.hxx b/odb/semantics/fundamental.hxx index 55ce322..75cbbf5 100644 --- a/odb/semantics/fundamental.hxx +++ b/odb/semantics/fundamental.hxx @@ -13,7 +13,7 @@ namespace semantics // Fundamental C++ types. // - struct fund_type: public type + struct fund_type: type { virtual string fq_name () const; @@ -27,84 +27,105 @@ namespace semantics fund_void (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} }; - struct fund_bool: fund_type - { - fund_bool (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} - }; - // // Integral. // - struct fund_char: fund_type + struct integral_type: fund_type + { + virtual bool + unsigned_ () const = 0; + }; + + struct fund_bool: integral_type + { + fund_bool (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return true;} + }; + + struct fund_char: integral_type { fund_char (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const; }; - struct fund_wchar: fund_type + struct fund_wchar: integral_type { fund_wchar (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const; }; - struct fund_char16: fund_type + struct fund_char16: integral_type { fund_char16 (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return true;} }; - struct fund_char32: fund_type + struct fund_char32: integral_type { fund_char32 (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return true;} }; - struct fund_signed_char: fund_type + struct fund_signed_char: integral_type { fund_signed_char (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return false;} }; - struct fund_unsigned_char: fund_type + struct fund_unsigned_char: integral_type { fund_unsigned_char (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return true;} }; - struct fund_short: fund_type + struct fund_short: integral_type { fund_short (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return false;} }; - struct fund_unsigned_short: fund_type + struct fund_unsigned_short: integral_type { fund_unsigned_short (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return true;} }; - struct fund_int: fund_type + struct fund_int: integral_type { fund_int (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return false;} }; - struct fund_unsigned_int: fund_type + struct fund_unsigned_int: integral_type { fund_unsigned_int (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return true;} }; - struct fund_long: fund_type + struct fund_long: integral_type { fund_long (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return false;} }; - struct fund_unsigned_long: fund_type + struct fund_unsigned_long: integral_type { fund_unsigned_long (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return true;} }; - struct fund_long_long: fund_type + struct fund_long_long: integral_type { fund_long_long (tree tn): node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return false;} }; - struct fund_unsigned_long_long: fund_type + struct fund_unsigned_long_long: integral_type { fund_unsigned_long_long (tree tn) : node (path ("<fundamental>"), 0, 0, tn) {} + virtual bool unsigned_ () const {return true;} }; // diff --git a/odb/traversal/enum.cxx b/odb/traversal/enum.cxx index 149f962..fd4ff89 100644 --- a/odb/traversal/enum.cxx +++ b/odb/traversal/enum.cxx @@ -14,13 +14,34 @@ namespace traversal // // + void underlies:: + traverse (type& u) + { + dispatch (u.type ()); + } + + // + // void enum_:: traverse (type& e) { + underlied (e); enumerates (e); } void enum_:: + underlied (type& e) + { + underlied (e, *this); + } + + void enum_:: + underlied (type& e, edge_dispatcher& d) + { + d.dispatch (e.underlied ()); + } + + void enum_:: enumerates (type& e) { enumerates (e, *this); diff --git a/odb/traversal/enum.hxx b/odb/traversal/enum.hxx index 1efccaa..c949934 100644 --- a/odb/traversal/enum.hxx +++ b/odb/traversal/enum.hxx @@ -12,10 +12,7 @@ namespace traversal { struct enumerates: edge<semantics::enumerates> { - enumerates () - { - } - + enumerates () {} enumerates (node_dispatcher& n) { node_traverser (n); @@ -27,12 +24,30 @@ namespace traversal struct enumerator: node<semantics::enumerator> {}; + struct underlies: edge<semantics::underlies> + { + underlies () {} + underlies (node_dispatcher& n) + { + node_traverser (n); + } + + virtual void + traverse (type&); + }; + struct enum_: node<semantics::enum_> { virtual void traverse (type&); virtual void + underlied (type&); + + virtual void + underlied (type&, edge_dispatcher&); + + virtual void enumerates (type&); virtual void |