https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103448

            Bug ID: 103448
           Summary: unexpected tuple collapse
           Product: gcc
           Version: 11.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: janezz55 at gmail dot com
  Target Milestone: ---

Here you have a fully working program, that instead of creating a

std::tuple<std::tuple<int&, int&>>

creates a

std::tuple<int&, int&>

something collapses the tuple of tuples into a single tuple. The workaround is
to replace the std::tuple() constructor call with a std::make_tuple() call.

https://wandbox.org/permlink/Q5P8iaUjThDKxJL9

#include <iostream>
#include <tuple>
#include <string_view>

template <typename T>
constexpr auto type_name() {
  std::string_view name, prefix, suffix;
#ifdef __clang__
  name = __PRETTY_FUNCTION__;
  prefix = "auto type_name() [T = ";
  suffix = "]";
#elif defined(__GNUC__)
  name = __PRETTY_FUNCTION__;
  prefix = "constexpr auto type_name() [with T = ";
  suffix = "]";
#elif defined(_MSC_VER)
  name = __FUNCSIG__;
  prefix = "auto __cdecl type_name<";
  suffix = ">(void)";
#endif
  name.remove_prefix(prefix.size());
  name.remove_suffix(suffix.size());
  return name;
}

template <std::size_t N>
constexpr auto split(auto&& t) noexcept requires(bool(N))
{
  constexpr auto n(std::tuple_size_v<std::remove_cvref_t<decltype(t)>>);
  static_assert(n && !(n % N));
  return [&]<auto ...I>(std::index_sequence<I...>) noexcept
  {
    return std::tuple(
      [&]<auto ...J>(std::index_sequence<J...>) noexcept
      {
        constexpr auto K(N * I);
        return std::forward_as_tuple(std::get<K + J>(t)...);
      }(std::make_index_sequence<N + I - I>())...
    );
  }(std::make_index_sequence<n / N>());
}

int main()
{
  auto t(split<2>(std::tuple(1, 2)));
  std::cout << type_name<decltype(t)>() << std::endl;

  return 0;
}

Reply via email to