Print spaces between each element using a fold exp

2020-04-10 01:32发布

问题:

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();
}

回答1:

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)...)



回答2:

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;
    }
};


回答3:

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.



回答4:

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