Last active
July 10, 2018 09:33
-
-
Save Angeart/ebe36410ce873896c618bc0400af875b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // This file is a "Hello, world!" in C++ language for wandbox-vscode. | |
| #include <iostream> | |
| #include <cstdlib> | |
| #include <cstdint> | |
| #include <type_traits> | |
| #include <utility> | |
| #include <memory> | |
| #include <vector> | |
| #include <array> | |
| #include <boost/core/demangle.hpp> | |
| #include <boost/variant.hpp> | |
| #include <boost/mpl/vector.hpp> | |
| #include <boost/mpl/at.hpp> | |
| #include <boost/mpl/find.hpp> | |
| #include <boost/serialization/strong_typedef.hpp> | |
| namespace util { | |
| template<class... T> | |
| struct inherit{ | |
| template<class...Args> | |
| inherit(Args&&...){}; | |
| }; | |
| template<class T> | |
| struct inherit<T> : T{ | |
| template<class...Args> | |
| inherit(Args&&...args) : T(std::forward<Args>(args)...){}; | |
| }; | |
| template<class H, class... T> | |
| struct inherit<H,T...> : H, inherit<T...> { | |
| template<class...Args> | |
| inherit(Args&&... args) : H(args...), inherit<T...>(std::forward<Args>(args)...){}; | |
| }; | |
| } | |
| namespace util { | |
| namespace class_identity_detail { | |
| using class_identifier_t = uint32_t; | |
| struct identity_factory { | |
| static class_identifier_t get_id() { | |
| static class_identifier_t value = 0; | |
| return value++; | |
| } | |
| }; | |
| template<class T> | |
| struct identity_holder { | |
| using value_type = class_identifier_t; | |
| using class_type = T; | |
| identity_holder() : value(identity_factory::get_id()) {}; | |
| static class_identifier_t get_identity() { | |
| static const identity_holder temp; | |
| return temp.get_internal_identity(); | |
| } | |
| private: | |
| class_identifier_t get_internal_identity() const { | |
| return this->value; | |
| } | |
| const class_identifier_t value; | |
| }; | |
| template<class T, class...Bases> | |
| struct class_identity : public inherit<Bases...>{ | |
| //using inherit<Bases...>::inherit; | |
| template<class...Args> | |
| class_identity(Args&&... args) : inherit<Bases...>(std::forward<Args>(args)...) {}; | |
| using base_type = class_identity; | |
| using identity_type = identity_holder<T>; | |
| virtual typename identity_type::value_type get_identity() const { | |
| return identity_type::get_identity(); | |
| } | |
| static typename identity_type::value_type get_identity_static() { | |
| return identity_type::get_identity(); | |
| } | |
| }; | |
| } | |
| namespace types { | |
| using class_identifier_t = class_identity_detail::class_identifier_t; | |
| } | |
| template<class T, class... Bases> | |
| using class_identity = class_identity_detail::class_identity<T, Bases...>; | |
| } | |
| namespace util { | |
| template <typename T> | |
| struct skip { | |
| T& t; | |
| std::size_t n; | |
| skip(T& v, std::size_t s) : t(v), n(s) {} | |
| auto begin() -> decltype(std::begin(t)) { | |
| return std::next(std::begin(t), n); | |
| } | |
| auto end() -> decltype(std::end(t)) { | |
| return std::end(t); | |
| } | |
| }; | |
| } | |
| template<class target_t> | |
| struct is_dumpable_t { | |
| template<class U> static auto check_internal(std::nullptr_t n) -> decltype(std::declval<U>().dump(), std::true_type{}); | |
| template<class U> static auto check_internal(...) -> std::false_type; | |
| static constexpr auto check() -> bool { return decltype(check_internal<target_t>(nullptr))::value; } | |
| }; | |
| template<class target_t> | |
| constexpr auto is_dumpable() -> bool { return is_dumpable_t<target_t>::check(); } | |
| template<class target_t> | |
| struct is_streamable_t { | |
| template<class U> static auto check_internal(std::nullptr_t n) -> decltype(std::cout << std::declval<U>(), std::true_type{}); | |
| template<class U> static auto check_internal(...) -> std::false_type; | |
| static constexpr auto check() -> bool { return decltype(check_internal<target_t>(nullptr))::value; } | |
| }; | |
| template<class target_t> | |
| constexpr auto is_streamable() -> bool { return is_streamable_t<target_t>::check(); } | |
| struct unused_t {}; | |
| struct indent_t { | |
| static constexpr uint32_t width = 4u; | |
| }; | |
| struct dumper_t : boost::static_visitor<void> { | |
| dumper_t() : indent(0u) {}; | |
| void set_indent(uint32_t indent_) { indent = indent_; } | |
| template<class target_t> | |
| auto operator()(const target_t& d) const -> std::enable_if_t<is_dumpable<target_t>(),void> { | |
| print_name<target_t>(); | |
| d.dump(this->indent + indent_t::width); | |
| }; | |
| template<class target_t> | |
| auto operator()(const target_t& d) const -> std::enable_if_t<!is_dumpable<target_t>() && !is_streamable<target_t>(), void> { | |
| print_name<target_t>(); | |
| std::cout << put_indent() << "--" << std::endl; | |
| }; | |
| template<class target_t> | |
| auto operator()(const target_t& d) const -> std::enable_if_t<is_streamable<target_t>(),void> { | |
| print_name<target_t>(); | |
| std::cout << put_indent() << d << std::endl; | |
| } | |
| private: | |
| template<class target_t> | |
| void print_name() const { | |
| std::cout << put_indent() << "[" << boost::core::demangle(typeid(target_t).name()) << "]" << std::endl; | |
| } | |
| private: | |
| const std::string put_indent() const { | |
| std::string str = ""; | |
| for([[maybe_unused]]uint32_t i = 0u; i < this->indent; ++i)str += " "; | |
| return str; | |
| } | |
| uint32_t indent; | |
| }; | |
| // template<> | |
| // auto dumper_t::operator()<unused_t>(const unused_t& d) const -> void { | |
| // }; | |
| template<class ... types_t> | |
| struct sequence_holder_t { | |
| using container_t = boost::mpl::vector<types_t...>; | |
| template<size_t index_v> | |
| using at_t = typename boost::mpl::at<container_t,boost::mpl::int_<index_v>>::type; | |
| template<class selected_t> | |
| static constexpr size_t at_v = boost::mpl::find<container_t,selected_t>::type::pos::value; | |
| }; | |
| template<class ... elems_t> | |
| struct bundle_t { | |
| using variant_t = boost::variant<unused_t,elems_t...>; | |
| using elem_size_t = std::integral_constant<size_t, sizeof...(elems_t) + 1>; | |
| using resolver_t = sequence_holder_t<unused_t,elems_t...>; | |
| std::array<variant_t,elem_size_t::value> v; | |
| template<class input_t> | |
| bundle_t(const input_t& in) { | |
| v[resolver_t::template at_v<input_t>] = in; | |
| } | |
| bundle_t() {}; | |
| virtual void dump(uint32_t indent = 0) const { | |
| for(const auto& item : util::skip(v,1)){ | |
| dumper_t dumper; | |
| dumper.set_indent(indent); | |
| boost::apply_visitor(dumper, item); | |
| } | |
| } | |
| template<class input_t> | |
| void add(const input_t& in) { | |
| v[resolver_t::template at_v<input_t>] = in; | |
| } | |
| template<class input_t> | |
| auto get() -> input_t { | |
| return boost::get<input_t>(v.at(resolver_t::template at_v<input_t>)); | |
| } | |
| }; | |
| struct base_t : util::class_identity<base_t> { | |
| }; | |
| struct int32_value_t : util::class_identity<int32_value_t, bundle_t<int>> { | |
| using base_type::base_type; | |
| }; | |
| struct float_value_t : util::class_identity<float_value_t, bundle_t<float>> { | |
| using base_type::base_type; | |
| }; | |
| struct test_t : util::class_identity<test_t, bundle_t<int32_value_t, float_value_t>> { | |
| using base_type::base_type; | |
| }; | |
| struct string_value_t : util::class_identity<string_value_t, bundle_t<std::string>> { | |
| using base_type::base_type; | |
| }; | |
| struct func_t : util::class_identity<func_t, bundle_t<string_value_t,test_t>> { | |
| using base_type::base_type; | |
| }; | |
| int main() | |
| { | |
| try { | |
| test_t t; | |
| t.add(float_value_t(10.0f)); | |
| t.add(int32_value_t(99)); | |
| func_t f; | |
| f.add(string_value_t(std::string("hoge"))); | |
| f.add(t); | |
| f.dump(); | |
| } catch(const std::exception& e) { | |
| std::cout << e.what() << std::endl; | |
| } | |
| std::cout << func_t::resolver_t::template at_v<test_t> << std::endl; | |
| std::cout << | |
| boost::core::demangle(typeid( | |
| func_t::resolver_t::at_t<1>::resolver_t::template at_t<1> | |
| ).name()) | |
| << std::endl; | |
| return EXIT_SUCCESS; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
demo
require boost & c++17