user3770234
user3770234

Reputation: 55

c++17 fold expression syntatx

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

  }

Upvotes: 1

Views: 343

Answers (2)

max66
max66

Reputation: 66230

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

Upvotes: 0

Jarod42
Jarod42

Reputation: 218098

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

Upvotes: 2

Related Questions