Skip to content

Instantly share code, notes, and snippets.

@Angeart
Last active July 10, 2018 09:33
Show Gist options
  • Select an option

  • Save Angeart/ebe36410ce873896c618bc0400af875b to your computer and use it in GitHub Desktop.

Select an option

Save Angeart/ebe36410ce873896c618bc0400af875b to your computer and use it in GitHub Desktop.
// 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;
}
@Angeart
Copy link
Author

Angeart commented Jul 10, 2018

demo

require boost & c++17

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment