4

Newer GCC introduced a new builtin __integer_pack to help it implement std::make_integer_sequence and friends. For Reasons(tm), I am unable to use this function, so I'm trying to reimplement it (and then use #define to replace the standard library usage)

It's used in the form __integer_pack(N)..., which expands its "return value". However I can't convince the type of my own templates to match this, with clang (10) erroring with:

error: pack expansion does not contain any unexpanded parameter packs

using make_integer_sequence = integer_sequence<_Tp, integer_pack(_Num)...>;

Is this even possible?

Here's what I've got so far:

#include <cstddef>


template <std::size_t...> struct index_sequence {};

template <std::size_t N, std::size_t... Is>
struct integer_pack : integer_pack<N - 1, N - 1, Is...> {};

template <std::size_t... Is>
struct integer_pack<0u, Is...> : index_sequence<Is...> { using type = index_sequence<Is...>; };


// Assume nothing below here can be changed.
#include <iostream>

/// Class template integer_sequence
template<typename _Tp, _Tp... _Idx>
struct integer_sequence
{
    typedef _Tp value_type;
    static constexpr size_t size() noexcept { return sizeof...(_Idx); }
};

// debugging aid
template<typename T, T... ints>
void print_sequence(integer_sequence<T, ints...> int_seq)
{
    std::cout << "The sequence of size " << int_seq.size() << ": ";
    ((std::cout << ints << ' '),...);
    std::cout << '\n';
}

template<typename _Tp, _Tp _Num>
using make_integer_sequence = integer_sequence<_Tp, integer_pack(_Num)...>;

int main()
{
    print_sequence(make_integer_sequence<int, 20>{});
}
Sisir
  • 4,584
  • 4
  • 26
  • 37
LordAro
  • 1,269
  • 3
  • 18
  • 35
  • As it says, you try to expand an instantiation of template rather than a pack. Plain vanilla C++ packs don't work this way, you'll need an extra step. – bipll Jul 21 '20 at 11:13
  • 1
    `__integer_pack` is a intrinsic to allow unique instantiation for `std::make_integer_sequence` instead of `O(n)` or `O(log(n))`. You cannot replicate that intrinsic, and you have to re-implement `std::make_integer_sequence` another way. – Jarod42 Jul 21 '20 at 11:41
  • Why do you think `integer_pack(_Num)...` should work? – user253751 Jul 21 '20 at 12:05
  • 2
    Perhaps [Implementation C++14 make_integer_sequence](https://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence) can help? – Ted Lyngmo Jul 21 '20 at 12:08
  • 1
    @user253751 because `__integer_pack(_Num)...` is what is used in the `utility` STL header – LordAro Jul 21 '20 at 12:21
  • @LordAro Is `__integer_pack` defined the same way as `integer_pack`? – user253751 Jul 21 '20 at 12:41

1 Answers1

4

No, this is not possible. __integer_pack is not a function, it is a placeholder that is expanded by the compiler into a parameter pack. This is not something you can replicate within the language.

You can look at how gcc implements replacing the call to __integer_pack with its expansion in gcc/cp/pt.c, starting at line 3750 currently. builtin_pack_fn_p() identifies calls to __integer_pack (the _p suffix means "predicate"), and expand_integer_pack performs the expansion.

You will need to write your own implementation (or copy an existing one) within the language.

ecatmur
  • 152,476
  • 27
  • 293
  • 366