From 4cb3716317207e3a6813b0d9ff779edc7fec91de Mon Sep 17 00:00:00 2001
From: Boris Kolpackov <boris@codesynthesis.com>
Date: Tue, 15 Oct 2013 07:01:17 +0200
Subject: Automatically map C++11 enum classes (strong enums)

---
 common/enum/driver.cxx       | 19 +++++++++++++++++++
 common/enum/test.hxx         | 29 ++++++++++++++++++++++++++---
 libcommon/common/config-vc.h |  6 ++++++
 libcommon/common/config.hxx  |  7 +++++++
 4 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/common/enum/driver.cxx b/common/enum/driver.cxx
index 6cc41af..2e1e678 100644
--- a/common/enum/driver.cxx
+++ b/common/enum/driver.cxx
@@ -33,6 +33,13 @@ main (int argc, char* argv[])
     object o;
     o.color_ = green;
     o.taste_ = object::sweet;
+    o.position_ = object::left;
+
+#ifdef HAVE_CXX11_ENUM
+    o.gender_ = object::gender::female;
+    o.scale_ = object::scale::ten;
+    o.yesno_ = object::yesno::yes;
+#endif
 
     {
       transaction t (db->begin ());
@@ -53,9 +60,21 @@ main (int argc, char* argv[])
 
       result r1 (db->query<object> (query::color == blue));
       result r2 (db->query<object> (query::taste == object::sweet));
+      result r3 (db->query<object> (query::position == object::left));
 
       assert (r1.empty ());
       assert (!r2.empty ());
+      assert (!r3.empty ());
+
+#ifdef HAVE_CXX11_ENUM
+      result r4 (db->query<object> (query::gender == object::gender::female));
+      result r5 (db->query<object> (query::scale == object::scale::ten));
+      result r6 (db->query<object> (query::yesno == object::yesno::yes));
+
+      assert (!r4.empty ());
+      assert (!r5.empty ());
+      assert (!r6.empty ());
+#endif
 
       t.commit ();
     }
diff --git a/common/enum/test.hxx b/common/enum/test.hxx
index c1609fd..98ff0e9 100644
--- a/common/enum/test.hxx
+++ b/common/enum/test.hxx
@@ -6,6 +6,7 @@
 #define TEST_HXX
 
 #include <odb/core.hxx>
+#include <common/config.hxx> // HAVE_CXX11_ENUM
 
 enum color {red, green, blue};
 
@@ -18,15 +19,37 @@ struct object
   color color_;
   enum taste {bitter, sweet, sour};
   taste taste_;
+
+  enum position {left = -1, center = 0, right = 1};
+  position position_;
+
+
+#ifdef HAVE_CXX11_ENUM
+  enum class gender {male, female};
+  enum class scale: unsigned char {one = 1, ten = 10, hundred = 100};
+  enum class yesno: bool {no, yes};
+
+  gender gender_;
+  scale scale_;
+  yesno yesno_;
+#endif
+
 };
 
 inline bool
 operator == (const object& x, const object& y)
 {
   return
-    x.id_ == y.id_ &&
-    x.color_ == y.color_ &&
-    x.taste_ == y.taste_;
+    x.id_ == y.id_
+    && x.color_ == y.color_
+    && x.taste_ == y.taste_
+    && x.position_ == y.position_
+#ifdef HAVE_CXX11_ENUM
+    && x.gender_ == y.gender_
+    && x.scale_ == y.scale_
+    && x.yesno_ == y.yesno_;
+#endif
+    ;
 }
 
 #endif // TEST_HXX
diff --git a/libcommon/common/config-vc.h b/libcommon/common/config-vc.h
index 17d1bd0..fe14255 100644
--- a/libcommon/common/config-vc.h
+++ b/libcommon/common/config-vc.h
@@ -15,6 +15,12 @@
 #if (defined(_MSC_VER) && _MSC_VER >= 1600) || \
     (defined(ODB_MSC_VER) && ODB_MSC_VER >= 1600)
 #  define HAVE_CXX11
+// Strongly typed enums are supported starting from VC++11.
+//
+#  if (defined(_MSC_VER) && _MSC_VER >= 1700) || \
+      (defined(ODB_MSC_VER) && ODB_MSC_VER >= 1700)
+#    define HAVE_CXX11_ENUM
+#  endif
 #endif
 
 #endif /* LIBCOMMON_COMMON_CONFIG_VC_H */
diff --git a/libcommon/common/config.hxx b/libcommon/common/config.hxx
index da45841..08cf0e5 100644
--- a/libcommon/common/config.hxx
+++ b/libcommon/common/config.hxx
@@ -9,6 +9,13 @@
 #  include <common/config-vc.h>
 #else
 #  include <common/config.h>
+
+// GCC supports strongly typed enums from 4.4 (forward -- 4.6),
+// Clang -- 2.9 (3.1).
+//
+#  ifdef HAVE_CXX11
+#    define HAVE_CXX11_ENUM
+#  endif
 #endif
 
 #endif // LIBCOMMON_COMMON_CONFIG_HXX
-- 
cgit v1.1