Skip to content

Latest commit

 

History

History
147 lines (114 loc) · 3.64 KB

237.md

File metadata and controls

147 lines (114 loc) · 3.64 KB
Info

Example

#include <cstdio>

auto main() -> int {
  std::puts("Hello world");        // during run-time
  @meta std::puts("Hello circle"); // during compilation-time
}
Hello circle
ASM generation compiler returned: 0
Hello circle
Execution build compiler returned: 0
Program returned: 0
Hello world

https://godbolt.org/z/bo48q1oWW

Puzzle

  • Can you implement to_tuple_with_names which returns named fields based on Circle Meta-model?
template<class T>
struct named {
  T value{};
  std::string_view name{};
};

template<class T> auto to_tuple_with_names(const T& t); // TODO

int main() {
    {
      struct empty { };

      const auto & t = to_tuple_with_names(empty{});

      expect(0 == std::tuple_size_v<std::remove_reference_t<decltype(t)>>);
    }

    {
      struct trade {
        std::int32_t price{42};
      };

      const auto & t = to_tuple_with_names(trade{});

      expect(1 == std::tuple_size_v<std::remove_reference_t<decltype(t)>>);
      expect(42 == std::get<0>(t).value and "price" == std::get<0>(t).name);
    }

    {
      struct trade {
        std::int32_t price{42};
        std::uint32_t quantity{1'000u};
      };

      const auto & t = to_tuple_with_names(trade{});

      expect(2 == std::tuple_size_v<std::remove_reference_t<decltype(t)>>);
      expect(42 == std::get<0>(t).value and "price" == std::get<0>(t).name);
      expect(1'000u == std::get<1>(t).value and "quantity" == std::get<1>(t).name);
    };
}

https://godbolt.org/z/sEhYvas7o

Solutions

template<class T> auto to_tuple_with_names(const T& t) {
    std::tuple<named<@member_types(T)>...> result;
    result...[:] = { t...[:], @member_names(T) } ...;
    return result;
}

https://godbolt.org/z/cbdofa9MY

template<class T> [[nodiscard]] auto to_tuple_with_names(const T& t) {
  constexpr auto to_tuple_with_names = []<class... TNames, class... TValues>(const TValues&... values) {
    return [&](const auto&... names) {
      return std::make_tuple(named<TValues>{values, names}...);
    };
  };
  return to_tuple_with_names(t.@member_values()...)(@member_names(T)...);
}

https://godbolt.org/z/EzhbT9q8P

template<class T> auto to_tuple_with_names(const T& t) {
    std::tuple<named<@member_types(T)>...> result;
    @meta for(int i = 0; i < @member_count(T); ++i) {
        std::get<i>(result) = { @member_value(t, i), @member_name(T, i) };
    }
    return result;
}
template<class T> auto to_tuple_with_names(const T& t) {
  return std::make_tuple(named<@member_types(T)>{@member_values(t), @member_names(T)}...);
}

https://godbolt.org/z/x9nWbWaEv

template <class T>
[[nodiscard]] constexpr auto to_tuple_with_names(const T &t) {
  return std::make_tuple(
      named<@member_types(T)>{t.@member_values(), @member_names(T)}...);
}

https://godbolt.org/z/a1GK46e6n

template<typename T, int I> auto get_member( T const & obj)
{
    return named{ obj.@member_value(I), @member_name(T, I) };
}
template<class T> auto to_tuple_with_names(const T& t){
    const int N = @member_count(T);
    return [&]<int ... Is >( std::integer_sequence<int, Is ... > const & )
    {
        return std::make_tuple(get_member<T,Is>(t)...);
    }(std::make_integer_sequence<int,N>{} );
};

https://godbolt.org/z/8rch9eTaW