Skip to content

Latest commit

 

History

History
190 lines (152 loc) · 5.93 KB

238.md

File metadata and controls

190 lines (152 loc) · 5.93 KB
Info

Example

int main() {
  @meta std::array types{@dynamic_type(int), @dynamic_type(bool)};
  ((std::cout << @type_string(@pack_type(types)) << ' '), ...); // int bool
}

https://godbolt.org/z/1chKfEdTh

Puzzle

  • Can you implement rotate_types and calls_verify_types by applying STL with @meta types?
template<auto N, class... Ts>
constexpr auto rotate_types(); // TODO

constexpr auto calls_verify_types(auto expected, auto given); // TODO

int main() {
  using namespace boost::ut;

  "rotate types"_test = [] {
    should("not change the input on empty list") = [] {
      expect(std::is_same_v<list<>, decltype(rotate_types<0>())>);
      static_assert(not []<class T>(T) { return requires { rotate_types<T::value>(); }; }(std::integral_constant<int, 1>{}));
    };

    should("return the same input with 1 element") = [] {
      expect(std::is_same_v<list<int>, decltype(rotate_types<0, int>())>);
      expect(std::is_same_v<list<int>, decltype(rotate_types<1, int>())>);
      static_assert(not []<class T>(T) { return requires { rotate_types<T::value, int>(); }; }(std::integral_constant<int, 2>{}));
    };

    should("rotate rigth input with multiple elements") = [] {
      expect(std::is_same_v<list<double, int, float>, decltype(rotate_types<0, double, int, float>())>);
      expect(std::is_same_v<list<int, float, double>, decltype(rotate_types<1, double, int, float>())>);
      expect(std::is_same_v<list<float, double, int>, decltype(rotate_types<2, double, int, float>())>);
      expect(std::is_same_v<list<double, int, float>, decltype(rotate_types<3, double, int, float>())>);

      static_assert([]<class T>(T) { return requires { rotate_types<T::value, double, int, float>(); }; }(std::integral_constant<int, 0>{}));
      static_assert([]<class T>(T) { return requires { rotate_types<T::value, double, int, float>(); }; }(std::integral_constant<int, 1>{}));
      static_assert(not []<class T>(T) { return requires { rotate_types<T::value, double, int, float>(); }; }(std::integral_constant<int, 4>{}));
      static_assert(not []<class T>(T) { return requires { rotate_types<T::value, double, int, float>(); }; }(std::integral_constant<int, 5>{}));
    };

    should("allow to unpack rotated types") = [] {
      constexpr auto expected = []<class T>(T){static_assert(std::is_same_v<list<float, double, int>, T>);};
      constexpr auto given = rotate_types<2, double, int, float>();

      calls_verify_types(expected, given);
    };
  };
}

https://godbolt.org/z/r3K5hMbso

Solutions

template<auto N, class... Ts> requires ( N <= sizeof...(Ts))
constexpr auto rotate_types()
{
    if constexpr ( sizeof...(Ts) <= 1)
        return list<Ts...>{};
    else
    {
        @meta std::array types{@dynamic_type(Ts)...};
        @meta std::rotate(types.begin(), types.begin() + N, types.end());
        return list<@pack_type(types)...>{};
    }
}

constexpr auto calls_verify_types(auto expected, auto given)
{
    expected(given);
}

https://godbolt.org/z/G9rqf7jT1

template <auto N, class... Ts> requires (N <= sizeof...(Ts))
constexpr auto rotate_types() {
  if constexpr (sizeof...(Ts) <= 1) {
    return list<Ts...>{};
  } else {
    @meta std::array types{@dynamic_type(Ts)...};
    @meta std::rotate(std::begin(types), std::next(std::begin(types), N), std::end(types));
    return list<@pack_type(types)...>{};
  }
}

constexpr auto calls_verify_types(auto expected, auto given) -> decltype(auto) {
  return expected(given);
}

https://godbolt.org/z/f3K7vTbT6

template<auto N, class... Ts>
requires (N <= sizeof...(Ts))
constexpr auto rotate_types() {
    if constexpr (sizeof...(Ts) <= 1) {
        return list<Ts...>{};
    } else {
        @meta auto types = std::array{@dynamic_type(Ts)...};
        @meta std::rotate(std::begin(types), std::next(std::begin(types), N), std::end(types));
        return list<@pack_type(types)...>{};
    }
}

constexpr auto calls_verify_types(auto expected, auto given) {
    return expected(given);
}

https://godbolt.org/z/eGsG6ff1P

template<auto N, class... Ts>
requires (N <= sizeof...(Ts))
constexpr auto rotate_types() {
    if constexpr (sizeof...(Ts) <= 1) {
        return list<Ts...>{};
    } else {
        @meta auto types = std::array{@dynamic_type(Ts)...};
        @meta std::rotate(std::begin(types), std::next(std::begin(types), N), std::end(types));
        return list<@pack_type(types)...>{};
    }
}

constexpr auto calls_verify_types(auto expected, auto given) {
    return expected(given);
}

https://godbolt.org/z/Y6ffnb4ex

template<auto N, class... Ts>
constexpr auto rotate_types() requires (N <= sizeof...(Ts)) {
    if constexpr (sizeof...(Ts) == 0) {
        return list{};
    } else {
        @meta std::array types{@dynamic_type(Ts)...};
        @meta std::rotate(types.begin(), types.begin() + N, types.end());
        return list<@pack_type(types)...>{};
    }
}

template <class... Ts>
constexpr auto calls_verify_types(auto expected, list<Ts...> given) {
    return verify_types<Ts...>(expected);
}

https://godbolt.org/z/r3fohYcad

template<auto N, class... Ts>
constexpr auto rotate_types() requires (N <= sizeof...(Ts)) {
  if constexpr (sizeof...(Ts) > 0) {
    @meta std::array types{@dynamic_type(@member_types(list<Ts...>))...};
    @meta std::rotate(std::begin(types), std::begin(types) + N, std::end(types));
    return list<@pack_type(types)...>{};
  } else {
    return list{};
  }
}

constexpr auto calls_verify_types(auto expected, auto given) {
  verify_types<@member_types(decltype(given))...>(expected);
}

https://godbolt.org/z/9jj9r6Ghn