6

I am using a fold expression to print elements in a variadic pack, but how do I get a space in between each element?

Currently the output is "1 234", the desired output is "1 2 3 4"

template<typename T, typename Comp = std::less<T> >
struct Facility
{
template<T ... list>
struct List
{
    static void print()
    {

    }
};
template<T head,T ... list>
struct List<head,list...>
{
    static void print()
    {
     std::cout<<"\""<<head<<" ";
     (std::cout<<...<<list);
    }
};
};

template<int ... intlist>
using IntList = typename Facility<int>::List<intlist...>;
int main()
{
 using List1 = IntList<1,2,3,4>;
 List1::print();
}
Rakete1111
  • 44,719
  • 11
  • 118
  • 156
Lim Ta Sheng
  • 351
  • 3
  • 6

4 Answers4

8

you can that

#include <iostream>

template<typename T>
struct Facility
{
template<T head,T ... list>
struct List
{
    static void print()
    {
     std::cout<<"\"" << head;
     ((std::cout << " " << list), ...);
      std::cout<<"\"";
    }
};
};

template<int ... intlist>
using IntList = typename Facility<int>::List<intlist...>;
int main()
{
 using List1 = IntList<1,2,3,4>;
 List1::print();
}

the fold expression ((std::cout << " " << list), ...) will expands to ((std::cout << " " << list1), (std::cout << " " << list2), (std::cout << " " << list3)...)

Tyker
  • 2,949
  • 8
  • 20
8

If you need space only between numbers (and not after the last or before the first too), you might do:

template <std::size_t... Is>
void print_seq(std::index_sequence<Is...>)
{
    const char* sep = "";
    (((std::cout << sep << Is), sep = " "), ...);
}

Demo

(It is similar to my "runtime version") for regular containers with for-loop.

Jarod42
  • 190,553
  • 13
  • 166
  • 271
7

In general, you use recursion for tasks like this.

You have to define what happens when there are 2 or more and 1 elements in the list and recursively fall back to those definitions:

template <int ...> struct List;
template <int First, int Second, int ... More> struct List {
    static void print() {
        std::cout << First << " ";
        List<Second, More ...>::print();
    }
};
template <int Last> struct List {
    static void print() {
        std::cout << Last;
    }
};
Markus Mayr
  • 3,868
  • 1
  • 18
  • 40
  • but if my packs have thousand of elements that recursion would fail. – Lim Ta Sheng Jul 11 '18 at 09:38
  • 4
    Packs might not be the best choice for having thousands of elements, though – deW1 Jul 11 '18 at 09:41
  • Recursion does `O(N)` instantiations, whereas folding expression allows `O(1)` instantiation (which shouldn't change runtime execution, but compilation time). – Jarod42 Apr 10 '19 at 08:52
1

You can reuse print() to achieve this behaviour. Afterall you are doing a fold operation which is by definition resursive.

Live Demo

template<T head,T ... rest_of_pack>

struct List<head , rest_of_pack...>
{
    static void print_()
    {
     std::cout<<head<<" ";
     List<rest_of_pack...>::print();

    }
};

If you want to process many elements this way you might run into problems with template depth (gcc for instance has a limit of 900). Lucky for you you can use the -ftemplate-depth= option to tweak this behaviour.

You can compile with -ftemplate-depth=100000 and make it work. Note that compilation time will skyrocket (most likely) or in thhe worst case you run out of memory.

Davide Spataro
  • 7,004
  • 1
  • 23
  • 36