// // json_direct_tuple_binder.hpp // json // // Created by Sam Jaffe on 2/26/17. // #pragma once #include namespace json { namespace binder { template class get_binder : public binder_impl { public: using value_type = typename std::remove_reference(std::declval()))>::type; get_binder(binder val_binder) : impl(std::move(val_binder)) { } get_binder(binder_impl const & val_binder = value_binder()) : impl(val_binder) { } virtual binder_impl* clone() const override { return new get_binder(*this); } virtual void parse(T& object, char const*& data, parser::options opts) const override { impl.parse(std::get(object), data, opts); } virtual void write(T const& val, std::ostream & data) const override { impl.write(std::get(val), data); } private: binder impl; }; #if __cpluscplus >= 201402L namespace detail { template tuple_binder make_tuple_binder(TupleIn && binds, std::index_sequence) { tuple_binder binder; using swallow = int[]; (void) swallow{ 0, (void(binder(get_binder(std::get(binds)))), 0)... }; return binder; } template tuple_binder make_array_binder(binder && binds, std::index_sequence) { tuple_binder binder; using swallow = int[]; (void) swallow{ 0, (void(binder(get_binder(binds))), 0)... }; return binder; } } template tuple_binder> make_tuple_binder(binder &&... binds) { return detail::make_tuple_binder>(std::make_tuple(binds...), std::make_index_sequence()); } template tuple_binder> make_tuple_binder(binder_impl &&... binds) { return detail::make_tuple_binder>(std::make_tuple(binder(binds)...), std::make_index_sequence()); } template tuple_binder> make_default_tuple_binder() { return detail::make_tuple_binder>(std::make_tuple(binder(value_binder())...), std::make_index_sequence()); } template tuple_binder> make_array_binder(binder && binds) { return detail::make_array_binder>(binds, std::make_index_sequence()); } template tuple_binder> make_array_binder(binder_impl const & binds = value_binder()) { return detail::make_array_binder>(binder(binds), std::make_index_sequence()); } #else namespace detail { template struct tuple_binder_helper; template <> struct tuple_binder_helper<0> { template tuple_binder & operator()(tuple_binder & bind) const { return bind; } }; template struct tuple_binder_helper { template tuple_binder & operator()(tuple_binder & bind, BindIn && ith, Ts &&... binders) const { using get_binder_t = get_binder::value-N>; return tuple_binder_helper()(bind(get_binder_t(std::forward(ith))), std::forward(binders)...); } }; template struct array_binder_helper; template <> struct array_binder_helper<1> { template tuple_binder & operator()(tuple_binder & bind, BindIn && ith) const { return bind; } }; template struct array_binder_helper { template tuple_binder & operator()(tuple_binder & bind, BindIn && ith) const { return array_binder_helper()(bind(get_binder(ith)), std::forward(ith)); } }; } template tuple_binder> make_tuple_binder(binder &&... binds) { tuple_binder> binder; return detail::tuple_binder_helper()(binder, std::forward(binds)...); } template tuple_binder> make_tuple_binder(binder_impl &&... binds) { tuple_binder> binder; return detail::tuple_binder_helper()(binder, json::binder::binder(binds)...); } template tuple_binder> make_default_tuple_binder() { tuple_binder> binder; return detail::tuple_binder_helper()(binder, json::binder::binder(value_binder())...); } template tuple_binder> make_array_binder(binder && binds) { tuple_binder> binder; return detail::array_binder_helper(binder, binds); } template tuple_binder> make_array_binder(binder_impl const & binds = value_binder()) { tuple_binder> binder; return detail::array_binder_helper(binder, json::binder::binder(binds)); } #endif } }