Browse Source

Adding C++11 compatible version of std::tuple/std::array make functions.

Samuel Jaffe 8 years ago
parent
commit
3350dba094
2 changed files with 79 additions and 10 deletions
  1. 66 0
      json/json_direct_get_binder.hpp
  2. 13 10
      json_binder_tuple.t.h

+ 66 - 0
json/json_direct_get_binder.hpp

@@ -81,5 +81,71 @@ namespace json { namespace binder {
   tuple_binder<std::array<T, N>> make_array_binder(binder_impl<T> const & binds = value_binder<T>()) {
     return detail::make_array_binder<std::array<T, N>>(binder<T>(binds), std::make_index_sequence<N>());
   }
+#else
+  namespace detail {
+    template <std::size_t> struct tuple_binder_helper;
+    
+    template <>
+    struct tuple_binder_helper<0> {
+      template <typename BindOut>
+      tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind) const { return bind; }
+    };
+    
+    template <std::size_t N>
+    struct tuple_binder_helper {
+      template <typename BindOut, typename BindIn, typename... Ts>
+      tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind, BindIn && ith, Ts &&... binders) const {
+        using get_binder_t = get_binder<BindOut, std::tuple_size<BindOut>::value-N>;
+        return tuple_binder_helper<N-1>()(bind(get_binder_t(std::forward<BindIn>(ith))),
+                                          std::forward<Ts>(binders)...);
+      }
+    };
+    
+    template <std::size_t> struct array_binder_helper;
+    
+    template <>
+    struct array_binder_helper<1> {
+      template <typename BindOut, typename BindIn>
+      tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind, BindIn && ith) const { return bind; }
+    };
+    
+    template <std::size_t N>
+    struct array_binder_helper {
+      template <typename BindOut, typename BindIn>
+      tuple_binder<BindOut> & operator()(tuple_binder<BindOut> & bind, BindIn && ith) const {
+        return array_binder_helper<N-1>()(bind(get_binder<BindOut, N-1>(ith)), std::forward<BindIn>(ith));
+      }
+    };
+  }
+  
+  template <typename... Ts>
+  tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder<Ts> &&... binds) {
+    tuple_binder<std::tuple<Ts...>> binder;
+    return detail::tuple_binder_helper<sizeof...(Ts)>()(binder, std::forward<Ts>(binds)...);
+  }
+  
+  template <typename... Ts>
+  tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder_impl<Ts> &&... binds) {
+    tuple_binder<std::tuple<Ts...>> binder;
+    return detail::tuple_binder_helper<sizeof...(Ts)>()(binder, json::binder::binder<Ts>(binds)...);
+  }
+  
+  template <typename... Ts>
+  tuple_binder<std::tuple<Ts...>> make_default_tuple_binder() {
+    tuple_binder<std::tuple<Ts...>> binder;
+    return detail::tuple_binder_helper<sizeof...(Ts)>()(binder, json::binder::binder<Ts>(value_binder<Ts>())...);
+  }
+  
+  template <typename T, std::size_t N>
+  tuple_binder<std::array<T, N>> make_array_binder(binder<T> && binds) {
+    tuple_binder<std::array<T, N>> binder;
+    return detail::array_binder_helper<N>(binder, binds);
+  }
+  
+  template <typename T, std::size_t N>
+  tuple_binder<std::array<T, N>> make_array_binder(binder_impl<T> const & binds = value_binder<T>()) {
+    tuple_binder<std::array<T, N>> binder;
+    return detail::array_binder_helper<N>(binder, json::binder::binder<T>(binds));
+  }
 #endif
 } }

+ 13 - 10
json_binder_tuple.t.h

@@ -19,9 +19,7 @@ public:
     char data[] = "[ 1, 2 ]";
     using tuple = std::tuple<int, int>;
     tuple out = std::make_tuple(0, 0);
-    auto binder = tuple_binder<std::tuple<int, int>>()
-      (get_binder<tuple, 0>())
-      (get_binder<tuple, 1>());
+    auto binder = make_default_tuple_binder<int, int>();
     parse(json::binder::bind(out, binder), data, allow_all);
     TS_ASSERT_EQUALS(out, std::make_tuple(1, 2));
   }
@@ -30,9 +28,7 @@ public:
     char data[] = "[ 1 ]";
     using tuple = std::tuple<int, int>;
     tuple out = std::make_tuple(0, 0);
-    auto binder = tuple_binder<std::tuple<int, int>>()
-      (get_binder<tuple, 0>())
-      (get_binder<tuple, 1>());
+    auto binder = make_default_tuple_binder<int, int>();
     TS_ASSERT_THROWS(parse(json::binder::bind(out, binder), data, allow_all),
                      json::malformed_json_exception);
     TS_ASSERT_EQUALS(out, std::make_tuple(1, 0));
@@ -42,11 +38,18 @@ public:
     char data[] = "[ 1, 2, 3 ]";
     using tuple = std::tuple<int, int>;
     tuple out = std::make_tuple(0, 0);
-    auto binder = tuple_binder<std::tuple<int, int>>()
-      (get_binder<tuple, 0>())
-      (get_binder<tuple, 1>());
+    auto binder = make_default_tuple_binder<int, int>();
     TS_ASSERT_THROWS(parse(json::binder::bind(out, binder), data, allow_all),
                      json::malformed_json_exception);
     TS_ASSERT_EQUALS(out, std::make_tuple(1, 2));
   }
-};
+  
+  void test_bind_to_tuple_with_multiple_types() {
+    char data[] = "[ 1, 0.5, \"hello\" ]";
+    using tuple = std::tuple<int, double, std::string>;
+    tuple out = std::make_tuple(0, 0.0, "");
+    auto binder = make_default_tuple_binder<int, double, std::string>();
+    TS_ASSERT_THROWS_NOTHING(parse(json::binder::bind(out, binder), data, allow_all));
+    TS_ASSERT_EQUALS(out, std::make_tuple(1, 0.5, "hello"));
+  }
+};