#ifndef TOML11_VISIT_HPP #define TOML11_VISIT_HPP #include "exception.hpp" #include "traits.hpp" #include "value.hpp" #include "version.hpp" namespace toml { inline namespace TOML11_INLINE_VERSION_NAMESPACE { namespace detail { template using visit_result_t = decltype(std::declval()(std::declval().as_boolean() ...)); template struct front_binder { template auto operator()(Args&& ... args) -> decltype(std::declval()(std::declval(), std::forward(args)...)) { return func(std::move(front), std::forward(args)...); } F func; T front; }; template front_binder, cxx::remove_cvref_t> bind_front(F&& f, T&& t) { return front_binder, cxx::remove_cvref_t>{ std::forward(f), std::forward(t) }; } template visit_result_t&, Args...> visit_impl(Visitor&& visitor, const basic_value& v, Args&& ... args); template visit_result_t&, Args...> visit_impl(Visitor&& visitor, basic_value& v, Args&& ... args); template visit_result_t, Args...> visit_impl(Visitor&& visitor, basic_value&& v, Args&& ... args); template visit_result_t visit_impl(Visitor&& visitor) { return visitor(); } template visit_result_t&, Args...> visit_impl(Visitor&& visitor, basic_value& v, Args&& ... args) { switch(v.type()) { case value_t::boolean : {return visit_impl(bind_front(visitor, std::ref(v.as_boolean ())), std::forward(args)...);} case value_t::integer : {return visit_impl(bind_front(visitor, std::ref(v.as_integer ())), std::forward(args)...);} case value_t::floating : {return visit_impl(bind_front(visitor, std::ref(v.as_floating ())), std::forward(args)...);} case value_t::string : {return visit_impl(bind_front(visitor, std::ref(v.as_string ())), std::forward(args)...);} case value_t::offset_datetime: {return visit_impl(bind_front(visitor, std::ref(v.as_offset_datetime())), std::forward(args)...);} case value_t::local_datetime : {return visit_impl(bind_front(visitor, std::ref(v.as_local_datetime ())), std::forward(args)...);} case value_t::local_date : {return visit_impl(bind_front(visitor, std::ref(v.as_local_date ())), std::forward(args)...);} case value_t::local_time : {return visit_impl(bind_front(visitor, std::ref(v.as_local_time ())), std::forward(args)...);} case value_t::array : {return visit_impl(bind_front(visitor, std::ref(v.as_array ())), std::forward(args)...);} case value_t::table : {return visit_impl(bind_front(visitor, std::ref(v.as_table ())), std::forward(args)...);} case value_t::empty : break; default: break; } throw type_error(format_error("[error] toml::visit: toml::basic_value " "does not have any valid type.", v.location(), "here"), v.location()); } template visit_result_t&, Args...> visit_impl(Visitor&& visitor, const basic_value& v, Args&& ... args) { switch(v.type()) { case value_t::boolean : {return visit_impl(bind_front(visitor, std::cref(v.as_boolean ())), std::forward(args)...);} case value_t::integer : {return visit_impl(bind_front(visitor, std::cref(v.as_integer ())), std::forward(args)...);} case value_t::floating : {return visit_impl(bind_front(visitor, std::cref(v.as_floating ())), std::forward(args)...);} case value_t::string : {return visit_impl(bind_front(visitor, std::cref(v.as_string ())), std::forward(args)...);} case value_t::offset_datetime: {return visit_impl(bind_front(visitor, std::cref(v.as_offset_datetime())), std::forward(args)...);} case value_t::local_datetime : {return visit_impl(bind_front(visitor, std::cref(v.as_local_datetime ())), std::forward(args)...);} case value_t::local_date : {return visit_impl(bind_front(visitor, std::cref(v.as_local_date ())), std::forward(args)...);} case value_t::local_time : {return visit_impl(bind_front(visitor, std::cref(v.as_local_time ())), std::forward(args)...);} case value_t::array : {return visit_impl(bind_front(visitor, std::cref(v.as_array ())), std::forward(args)...);} case value_t::table : {return visit_impl(bind_front(visitor, std::cref(v.as_table ())), std::forward(args)...);} case value_t::empty : break; default: break; } throw type_error(format_error("[error] toml::visit: toml::basic_value " "does not have any valid type.", v.location(), "here"), v.location()); } template visit_result_t, Args...> visit_impl(Visitor&& visitor, basic_value&& v, Args&& ... args) { switch(v.type()) { case value_t::boolean : {return visit_impl(bind_front(visitor, std::move(v.as_boolean ())), std::forward(args)...);} case value_t::integer : {return visit_impl(bind_front(visitor, std::move(v.as_integer ())), std::forward(args)...);} case value_t::floating : {return visit_impl(bind_front(visitor, std::move(v.as_floating ())), std::forward(args)...);} case value_t::string : {return visit_impl(bind_front(visitor, std::move(v.as_string ())), std::forward(args)...);} case value_t::offset_datetime: {return visit_impl(bind_front(visitor, std::move(v.as_offset_datetime())), std::forward(args)...);} case value_t::local_datetime : {return visit_impl(bind_front(visitor, std::move(v.as_local_datetime ())), std::forward(args)...);} case value_t::local_date : {return visit_impl(bind_front(visitor, std::move(v.as_local_date ())), std::forward(args)...);} case value_t::local_time : {return visit_impl(bind_front(visitor, std::move(v.as_local_time ())), std::forward(args)...);} case value_t::array : {return visit_impl(bind_front(visitor, std::move(v.as_array ())), std::forward(args)...);} case value_t::table : {return visit_impl(bind_front(visitor, std::move(v.as_table ())), std::forward(args)...);} case value_t::empty : break; default: break; } throw type_error(format_error("[error] toml::visit: toml::basic_value " "does not have any valid type.", v.location(), "here"), v.location()); } } // detail template detail::visit_result_t visit(Visitor&& visitor, Args&& ... args) { return detail::visit_impl(std::forward(visitor), std::forward(args)...); } } // TOML11_INLINE_VERSION_NAMESPACE } // toml #endif // TOML11_VISIT_HPP