#ifndef INCLUDED_IMPORTEXPORT_H #define INCLUDED_IMPORTEXPORT_H #include "generic/callback.h" #include "string/string.h" template struct Property { // todo: just return T, don't use continuation passing style Callback &returnz)> get; Callback set; }; // implementation template struct PropertyImpl { static void Export(const Self &self, const Callback &returnz) { returnz(self); } static void Import(Self &self, T value) { self = value; } }; namespace detail { template using propertyimpl_self = typename std::remove_reference>::type; template using propertyimpl_other = get_argument; template using propertyimpl_other_free = get_argument; } // adaptor template< class Self, class T = Self, class I = PropertyImpl > struct PropertyAdaptor { using Type = Self; using Other = T; using Get = ConstReferenceCaller &), I::Export>; using Set = ReferenceCaller; }; template< class T, class I > struct PropertyAdaptorFree { using Other = T; using Get = FreeCaller &), I::Export>; using Set = FreeCaller; }; // explicit full template Property make_property(typename A::Type &self) { return {typename A::Get(self), typename A::Set(self)}; } template Property make_property() { return {typename A::Get(), typename A::Set()}; } // explicit impl template, class T = detail::propertyimpl_other> using property_impl = PropertyAdaptor; template> Property make_property(Self &self) { return make_property>(self); } template> using property_impl_free = PropertyAdaptorFree; template> Property make_property() { return make_property>(); } // implicit template Property make_property(Self &self) { return make_property>(self); } // chain template Property> make_property_chain(detail::propertyimpl_self &it) { using DST = detail::propertyimpl_other; using SRC = detail::propertyimpl_self; using X = detail::propertyimpl_self; using A = property_impl; struct I { static void ExportThunk(const Callback &self, SRC value) { PropertyImpl::Export(value, self); } static void Export(const X &self, const Callback &returnz) { A::Get::thunk_(self, ConstReferenceCaller, void(SRC), ExportThunk>(returnz)); } static void Import(X &self, DST value) { SRC out; PropertyImpl::Import(out, value); A::Set::thunk_(self, out); } }; return make_property>(it); } template Property> make_property_chain() { using DST = detail::propertyimpl_other; using SRC = detail::propertyimpl_self; using A = property_impl_free; struct I { static void ExportThunk(const Callback &self, SRC value) { PropertyImpl::Export(value, self); } static void Export(const Callback &returnz) { A::Get::thunk_(nullptr, ConstReferenceCaller, void(SRC), ExportThunk>(returnz)); } static void Import(DST value) { SRC out; PropertyImpl::Import(out, value); A::Set::thunk_(nullptr, out); } }; return make_property>(); } // specializations template<> struct PropertyImpl { static void Export(const CopiedString &self, const Callback &returnz) { returnz(self.c_str()); } static void Import(CopiedString &self, const char *value) { self = value; } }; #endif