Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite Tuple's impl to not be recursive #420

Open
danakj opened this issue Dec 6, 2023 · 1 comment
Open

Rewrite Tuple's impl to not be recursive #420

danakj opened this issue Dec 6, 2023 · 1 comment
Labels
design Design of the library systems as a whole, such as concepts

Comments

@danakj
Copy link
Collaborator

danakj commented Dec 6, 2023

https://thephd.dev/sol3-compile-times-binary-sizes

The alternative fix is to use a std::tuple. Unfortunately, tuples are a poor idea in practice, especially on VC++ 2017. Currently, VC++’s tuple is implemented recursively, with some 20+ constructors invoked recursively on itself until it reaches the empty tuple. To go back to the 260 elements from before, that’s quite the Russian Doll of template struct instantiations, all different from each other by the order of arguments…! So I either pay the cost of a recursive template instantiation from VC++ tuple (or roll my own tuple, or take one off the shelf from boost::hana), or eat the cost of a recursive function instantiation to process the arguments in order so I can call the function.

These functions are recursive in order to find the Tuple storage for an index:

template <size_t I, class S>
static constexpr const auto& find_tuple_storage(const S& storage) {
  return find_tuple_storage(storage, std::integral_constant<size_t, I>());
}

template <size_t I, class S>
static constexpr const auto& find_tuple_storage(
    const S& storage, std::integral_constant<size_t, I>) {
  return find_tuple_storage(static_cast<const S::Super&>(storage),
                            std::integral_constant<size_t, I - 1>());
}

template <class S>
static constexpr const S& find_tuple_storage(
    const S& storage, std::integral_constant<size_t, 0>) {
  return storage;
}

template <size_t I, class S>
static constexpr auto& find_tuple_storage_mut(S& storage) {
  return find_tuple_storage_mut(storage, std::integral_constant<size_t, I>());
}

template <size_t I, class S>
static constexpr auto& find_tuple_storage_mut(
    S& storage, std::integral_constant<size_t, I>) {
  return find_tuple_storage_mut(static_cast<S::Super&>(storage),
                                std::integral_constant<size_t, I - 1>());
}

template <class S>
static constexpr S& find_tuple_storage_mut(S& storage,
                                           std::integral_constant<size_t, 0>) {
  return storage;
}

Supposedly libc++'s tuple does not require recursion, or maybe this recursion is okay but it has a different type S at each step so I don't think this is okay.

@danakj danakj added the design Design of the library systems as a whole, such as concepts label Dec 6, 2023
@danakj
Copy link
Collaborator Author

danakj commented Dec 6, 2023

Ah yes and the ctors are recursive:

  template <class... Us>
  constexpr inline TupleStorage(T& value, Us&&... more) noexcept
      : Super(::sus::forward<Us>(more)...),
        value(::sus::mem::addressof(value)) {}

libc++ does some funky multi-inheritance thing which I didn't understand the point of but I guess it's this.

@danakj danakj added this to the Containers library milestone Dec 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design Design of the library systems as a whole, such as concepts
Projects
None yet
Development

No branches or pull requests

1 participant