#pragma once #include #include #include #include #include #include namespace mstch { struct config { static std::function escape; }; namespace internal { template class object_t { public: const N& at(const std::string& name) const { cache[name] = (methods.at(name))(); return cache[name]; } bool has(const std::string name) const { return methods.count(name) != 0; } protected: template void register_methods(S* s, std::map methods) { for(auto& item: methods) this->methods.insert({item.first, std::bind(item.second, s)}); } private: std::map> methods; mutable std::map cache; }; template class is_fun { private: using not_fun = char; using fun_without_args = char[2]; using fun_with_args = char[3]; template struct really_has; template static fun_without_args& test( really_has*); template static fun_with_args& test( really_has*); template static not_fun& test(...); public: static bool const no_args = sizeof(test(0)) == sizeof(fun_without_args); static bool const has_args = sizeof(test(0)) == sizeof(fun_with_args); }; template using node_renderer = std::function; template class lambda_t { public: template lambda_t(F f, typename std::enable_if::no_args>::type* = 0): fun([f](node_renderer renderer, const std::string&) { return renderer(f()); }) { } template lambda_t(F f, typename std::enable_if::has_args>::type* = 0): fun([f](node_renderer renderer, const std::string& text) { return renderer(f(text)); }) { } std::string operator()(node_renderer renderer, const std::string& text = "") const { return fun(renderer, text); } private: std::function renderer, const std::string&)> fun; }; } using node = boost::make_recursive_variant< std::nullptr_t, std::string, int, double, bool, internal::lambda_t, std::shared_ptr>, std::map, std::vector>::type; using object = internal::object_t; using lambda = internal::lambda_t; using map = std::map; using array = std::vector; std::string render( const std::string& tmplt, const node& root, const std::map& partials = std::map()); }