Browse Source

Adding C++14 feature for constructing array/tuple bindings of guaranteed correct size, with much lower verbosity.

Samuel Jaffe 8 years ago
parent
commit
fce4057b40
1 changed files with 47 additions and 0 deletions
  1. 47 0
      json/json_direct_get_binder.hpp

+ 47 - 0
json/json_direct_get_binder.hpp

@@ -7,6 +7,8 @@
 
 #pragma once
 
+#include <tuple>
+
 namespace json { namespace binder {
   template <typename T, std::size_t I>
   class get_binder : public binder_impl<T> {
@@ -35,4 +37,49 @@ namespace json { namespace binder {
   private:
     binder<value_type> impl;
   };
+  
+#if __cpluscplus >= 201402L
+  namespace detail {
+    template <typename TupleOut, typename TupleIn, std::size_t... Indexes>
+    tuple_binder<TupleOut> make_tuple_binder(TupleIn && binds, std::index_sequence<Indexes...>) {
+      tuple_binder<TupleOut> binder;
+      using swallow = int[];
+      (void) swallow{ 0, (void(binder(get_binder<TupleOut, Indexes>(std::get<Indexes>(binds)))), 0)... };
+      return binder;
+    }
+    
+    template <typename TupleOut, typename T, std::size_t... Indexes>
+    tuple_binder<TupleOut> make_array_binder(binder<T> && binds, std::index_sequence<Indexes...>) {
+      tuple_binder<TupleOut> binder;
+      using swallow = int[];
+      (void) swallow{ 0, (void(binder(get_binder<TupleOut, Indexes>(binds))), 0)... };
+      return binder;
+    }
+  }
+  
+  template <typename... Ts>
+  tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder<Ts> &&... binds) {
+    return detail::make_tuple_binder<std::tuple<Ts...>>(std::make_tuple(binds...), std::make_index_sequence<sizeof...(Ts)>());
+  }
+
+  template <typename... Ts>
+  tuple_binder<std::tuple<Ts...>> make_tuple_binder(binder_impl<Ts> &&... binds) {
+    return detail::make_tuple_binder<std::tuple<Ts...>>(std::make_tuple(binder<Ts>(binds)...), std::make_index_sequence<sizeof...(Ts)>());
+  }
+  
+  template <typename... Ts>
+  tuple_binder<std::tuple<Ts...>> make_default_tuple_binder() {
+    return detail::make_tuple_binder<std::tuple<Ts...>>(std::make_tuple(binder<Ts>(value_binder<Ts>())...), std::make_index_sequence<sizeof...(Ts)>());
+  }
+  
+  template <typename T, std::size_t N>
+  tuple_binder<std::array<T, N>> make_array_binder(binder<T> && binds) {
+    return detail::make_array_binder<std::array<T, N>>(binds, std::make_index_sequence<N>());
+  }
+  
+  template <typename T, std::size_t N>
+  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>());
+  }
+#endif
 } }