// // json_direct_tuple_binder.hpp // json // // Created by Sam Jaffe on 2/26/17. // #pragma once #include "json_binder.hpp" #include "json_direct_binder.hpp" #include "json_tuple_binder.hpp" #include #include namespace json { namespace binder { template class get_binder : public binder_impl { // Maybe a reference type using ith_type = decltype(std::get(std::declval())); public: using value_type = typename std::remove_reference::type; get_binder() : impl(value_binder()) {} get_binder(binder val_binder) : impl(std::move(val_binder)) {} get_binder(binder_impl const & val_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 { constexpr auto get_index = std::tuple_size::value - N; using get_binder_t = get_binder; 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 &&) 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 }}