Skip to content

Latest commit

 

History

History
149 lines (115 loc) · 4.05 KB

366.md

File metadata and controls

149 lines (115 loc) · 4.05 KB
Info

Example

template<auto N> struct counter {
  static constexpr auto value = N;
};

[[nodiscard]] consteval auto next() {
  for (auto i = 0;; ++i) {
    if (auto mi = substitute(^counter, { std::meta::reflect_value(i) }); std::meta::is_incomplete_type(mi)) {
      return std::meta::value_of<decltype(i)>(std::meta::static_data_members_of(mi)[0]);
    }
  }
}

static_assert(next() == 0);
static_assert(next() == 1);

https://godbolt.org/z/91M56a5dd

Puzzle

  • Can you implement compile-time type list?
template<class T> using append_t;// TODO
template<auto = []{}> using get_list_t; // TODO

int main() {
  static_assert(typeid(get_list_t<>{}) == typeid(type_list<>));

  append_t<int>{};
  static_assert(typeid(get_list_t<>{}) == typeid(type_list<int>));

  append_t<float>{};
  static_assert(typeid(get_list_t<>{}) == typeid(type_list<int, float>));
}

https://godbolt.org/z/W7s5TW8ss

Solutions

template<auto> struct type_list_impl;

consteval auto append(auto new_member) {
  std::vector<std::meta::info> members{};
  for (auto i = 0;; ++i) {
    if (auto mi = substitute(^type_list_impl, { std::meta::reflect_value(i) }); std::meta::is_incomplete_type(mi)) {
      std::vector<std::meta::nsdm_description> new_members{};
      for (const auto& member: members) {
        new_members.push_back({std::meta::type_of(member), {.name = std::meta::name_of(member)}});
      }
      const char name[]{'_', char(i+'0'), 0};
      new_members.push_back({{new_member}, {.name = std::string_view(name, 2)}});
      return define_class(mi, new_members);
    } else {
      members = std::meta::nonstatic_data_members_of(mi);
    }
  }
}

consteval auto get_list(auto type_list) {
  std::vector<std::meta::info> members{};
  for (auto i = 0;; ++i) {
    if (auto mi = substitute(^type_list_impl, { std::meta::reflect_value(i) }); std::meta::is_incomplete_type(mi)) {
      break;
    } else {
      members = std::meta::nonstatic_data_members_of(mi);
    }
  }
  std::vector<std::meta::info> new_members{};
  for (auto member : members) {
    new_members.push_back(std::meta::type_of(member));
  }
  return substitute(type_list, new_members);
}

template<class...> struct type_list{};

template<class T> using append_t = [:append(^T):];
template<auto = []{}> using get_list_t = [:get_list(^type_list):];

int main() {
  static_assert(typeid(get_list_t<>{}) == typeid(type_list<>));

  append_t<int>{};
  static_assert(typeid(get_list_t<>{}) == typeid(type_list<int>));

  append_t<float>{};
  static_assert(typeid(get_list_t<>{}) == typeid(type_list<int, float>));
}

https://godbolt.org/z/P6sTdPEG8

template<class...> struct type_list {};
template<auto> struct nth { auto friend get(nth); auto friend get(nth); };
template<auto N, class T> struct set { auto friend get(nth<N>) { return T{}; } };

template<class T, template<class...> class TList, class... Ts> auto append_impl(TList<Ts...>) -> TList<Ts..., T>;

template<class T, auto N = 0, auto unique = []{}>
consteval auto append() {
    if constexpr (requires { get(nth<N>{}); }) {
        append<T, N+1, unique>();
    } else if constexpr (N == 0) {
        void(set<N, type_list<T>>{});
    } else {
        void(set<N, decltype(append_impl<T>(get(nth<N-1>{})))>{});
    }
}

template<auto unique = []{}, auto N = 0>
consteval auto get_list() {
    if constexpr (requires { get(nth<N>{}); }) {
        return get_list<unique, N+1>();
    } else if constexpr (N == 0) {
        return type_list{};
    } else {
        return get(nth<N-1>{});
    }
}

int main() {
  static_assert(typeid(get_list()) == typeid(type_list<>));

  append<int>();
  static_assert(typeid(get_list()) == typeid(type_list<int>));

  append<float>();
  static_assert(typeid(get_list()) == typeid(type_list<int, float>));
}

https://godbolt.org/z/d7GrW1j76