1

I have problem of make code working of fold expression in line 18 and line 23

I want make it such as have this result

"1 2 3 4"
"9 0 -1 -200"
"abc"
" world"
"Empty List"

As if the list is empty you will print "Empty List", if not, if the type is char it won't print space and if the type is not char, it will print space in between.

I tried using ((std::cout<<" " << list), ...); but it will print extra space which I don't want so I store in a temp string and later erase it.

Anyone can help?

#include <iostream>
#include <string>
template<int ... intlist>
using IntList = typename Facility<int>::List<intlist...>;

template<char ... charlist>
using CharList = typename Facility<char>::List<charlist...>;

template<short ... shortlist>
using ShortList = typename Facility<short>::List<shortlist...>;

template<unsigned short ... shortlist>
using UnsignedShortList = typename Facility<unsigned short>::List<shortlist...>;

template<long ... list>
using LongList = typename Facility<long>::List<list...>;

template<typename T , typename Comp=std::less<T>>
struct Facility
{
  template<T ... list> 
  struct List
  {
    static void print()
    {
      std::string str; 
      str ="\"";
      if(sizeof...(list)== 0)
      {
         str+="Empty List";
      }
      else if (std::is_same<T, char>::value)
      {
        str+=(... + list);
         //((std::cout<< list), ...);
      }
      else
      {
        str+=((" " + list), ...);
        //((std::cout<<" " << list), ...);
        str.erase(0,1);
      }
      str+="\"";
      std::cout << str << std::endl;
    }  
  }; 
};

int main()
{
    using List1 = IntList<1,2,3,4>;
    using List2 = IntList<9, 0, -1, -200>;
    List1::print();
    List2::print();

    using String1 = CharList<'a', 'b', 'c'>;
    using String2 = CharList<' ', 'w', 'o', 'r', 'l', 'd' >;
    using EmptyString = CharList<>;
    String1::print();
    String2::print();
    EmptyString::print();

  }

2 Answers2

2

As I understand you might use:

template<typename T>
struct Facility
{
    template <T ... list>
    struct List
    {
        static void print()
        {
            std::cout << '"';
            if constexpr (sizeof...(list) == 0)
            {
                 std::cout << "Empty List";
            }
            else if constexpr (std::is_same<T, char>::value)
            {
                ((std::cout << list), ...);
            }
            else
            {
                [[maybe_unused]]  const char* sep = "";
                (((std::cout << sep << list), sep = " "), ...);
            }
            std::cout << '"' << std::endl;
        }  
    }; 
};

With usage:

int main() {
    Facility<int>::List<>::print();
    Facility<int>::List<42, 42>::print();
    Facility<char>::List<'h', 'e', 'l', 'l', 'o'>::print();
}

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • thank I never thought of set the space in later part of comma – user3770234 Jul 19 '18 at 14:31
  • 1
    it is the C++17 equivalent of the [for version](https://stackoverflow.com/a/35373017/2684539) of [idioms-for-joining display](https://stackoverflow.com/questions/35372784/idioms-for-for-each-except-the-last-or-between-each-consecutive-pair-of-el) – Jarod42 Jul 19 '18 at 14:36
  • I notice using this method have a issue if performance , if there is 20,000 element it compile very slow – user3770234 Jul 19 '18 at 14:45
  • Then, you might try `static const T args[] = {list...};` and use the for loop version. – Jarod42 Jul 19 '18 at 14:51
  • LOL Those are what coders call memes. Very entertaining. Thanks you both of you. – sandthorn Jul 19 '18 at 14:57
0

Another solution could be the use of a std::ostringstream and remove the last char (placing the space in last position)

    std::ostringstream oss;

    ((oss << list << ' '), ...);

    str += oss.str().substr(0, oss.str().size()-1);

The following is a full compiling example

#include <string>
#include <iostream>
#include <sstream>

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

      str = "\"";

      if(sizeof...(list)== 0)
      {
         str += "Empty List";
      }
      else if (std::is_same<T, char>::value)
      {
        std::ostringstream oss;

        ((oss << list), ...);

        str += oss.str();
      }
      else
      {
        std::ostringstream oss;

        ((oss << list << ' '), ...);

        str += oss.str().substr(0, oss.str().size()-1);
      }

      str += "\"";

      std::cout << str << std::endl;
    }  
  }; 
};

int main ()
{
  Facility<int>::List<1, 2, 3, 4> f;

  f.print();
}
max66
  • 65,235
  • 10
  • 71
  • 111