How to make grouped or paired fold of parameter pack?

parameter pack folding
parameter packs not expanded with
c++ variadic templates unpack
cpp pack folding
c++ parameter pack folding
c iterate over parameter pack
c parameter pack expansion
variadic templates c++17
template<class Msg, class... Args>
std::wstring descf(Msg, Args&&... args) {
    std::wostringstream woss;

    owss << Msg << ". " << ... << " " << args << ": '" << args << "' ";//not legal at all

    //or

    owss << Msg << ". " << args[0] << ": '" << args[1] << "'  " << args[2] << ": '" << args[3] << "' "; //... pseudo code, and so on...
}

I know I can just use a list of pairs or something like that instead, but I'm interested in how to do this while keeping the syntax of the function to:

const auto formatted = descf(L"message", "arg1", arg1, "arg2", arg2);

You can use a fold expression! It's not the prettiest*, but it's shorter than all the non-fold solutions presented:

template<class T, class ... Args>
std::wstring descf(T msg, Args&&... args) {
    std::wostringstream owss;
    owss << msg << ". ";

    std::array<const char*, 2> tokens{": '", "' "};
    int alternate = 0;
    ((owss << args << tokens[alternate], alternate = 1 - alternate), ...);

    return owss.str();
}

Demo with sample output: https://godbolt.org/z/Gs8d2x

We perform a fold over the comma operator, where each operand is an output of one args and the alternating token, plus switching the token index (the latter two are combined with another comma operator).

*To a reader familiar with fold expressions (and the comma operator) this is probably the "best" code, but for everyone else it's utter gibberish, so use your own judgement whether you want to inflict this on your code base.

Parameter pack(since C++11), Fold-expressions (C++17) A template with at least one parameter pack is called a variadic template. list provided that all following parameters can be deduced from the function arguments, or have default arguments: struct Tuple { }; template<typename T1, typename T2> struct Pair {}; template<class . A template parameter pack is a template parameter that accepts zero or more template arguments (non-types, types, or templates). A function parameter pack is a function parameter that accepts zero or more function arguments. A template with at least one parameter pack is called a variadic template.

This is easy with a couple of helper functions that follow the following pattern.

void helper() {}

template <class T1, class T2, class ... T>
void helper(T1 t1, T2 t2, T ... t)
{
     do_single_pair(t1, t2);
     helper(t...);
}

This is not a fold expression but the net result is the same.

Generalized Unpacking and Parameter Pack Slicing, Audience: Evolution Working Group Heads and Tails; Divide-and-Conquer; Unpacking and Fold Does this make std::apply (and std::make_from_tuple ) obsolete? Parameter pack slicing, particularly single valued slicing (i.e. of template instantiations by about half, by swapping pairs of arguments� c++ documentation: Parameter packs. This modified text is an extract of the original Stack Overflow Documentation created by following contributors and released under CC BY-SA 3.0

I suppose you can try with an index and a ternary operator.

Something as follows

template <typename ... Args>
std::wstring descf (std::wstring const & Msg, Args && ... args)
 {
   std::wostringstream woss;

   int i = 0;

   ((woss << Msg << ". "), ... ,(woss << args << (++i & 1 ? ": '" : "' ")));

   return woss.str();
 }

Homogeneous variadic function parameters, Legal since C++11: T is not a parameter pack, but vs is. template <class T, T vs > void foo(); This paper explores the design space around making the first example legal. Iterate over the elements, Range-based for, Fold expressions When paired with function parameter packs, this creates a syntactic� How to make grouped or paired fold of parameter pack? Do any countries have a procedure that allows a constituent part of that country to become independent unilaterally? more hot questions

The following code should do the trick. The parameter pack is expanded in an initializer list.

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

template <typename...Args>
std::string descf(std::string msg, Args &&... args)
{
   auto argumentsVector = std::vector<std::string>{args...};

   std::stringstream ss;
   ss << msg << ". ";

   for (auto i = std::size_t{0}; i < argumentsVector.size() - 1; ++i)
      ss << argumentsVector[i] << ": '" << argumentsVector[i+1] << "' ";

   auto result = ss.str();
   if (!argumentsVector.empty())
       result.pop_back();
   return result;
}

int main()
{
   std::cout << descf("message", "arg1", "1", "arg2", "2") << std::endl;
}

Fold Expressions, cout << sum2(1, 2, 3, 4, 5, 6, 7) << "\n";. } Run. Fold expressions over a parameter pack. Also by default we get the following values for empty parameter packs:� How to make grouped or paired fold of parameter pack? How can an employer better accommodate workers on the autism-spectrum to reduce absence from work? Is this platform game level winnable?

With std::index_sequence:

template <class Msg, class... Pairs>
std::wstring descf_pair(const Msg& msg, const Pairs&... pairs)
{
    std::wstringstream woss;

    woss << msg << ". ";
    auto sep = L"";
    ((woss << sep << std::get<0>(pairs) << L": '"
                  << std::get<1>(pairs) << L"'", sep = L"  "), ...);
    return woss.str();
}

template <class Msg, std::size_t... Is, class Tuple>
decltype(auto) descf_impl(const Msg& msg, std::index_sequence<Is...>, Tuple&& t)
{
    return descf_pair(msg, std::tie(std::get<2 * Is>(t), std::get<2 * Is + 1>(t))...);
}

template <class Msg, typename ... Ts>
std::wstring descf(const Msg& msg, const Ts&... ts)
{
    static_assert(sizeof...(Ts) % 2 == 0);

    return descf_impl(msg,
                      std::make_index_sequence<sizeof...(Ts) / 2>(),
                      std::tie(ts...));
}

Demo

Intrinsic Currying for C++ Template Metaprograms, make fullsome use of a Turing complete language, and rely on explicit recursion operators1 such as map and fold, standard C++ library support is regrettably std::common_type_t obtains a common type from its parameter pack argument6. function class F, to be paired with an arity type N, as a fellow base class, as in. How to make grouped or paired fold of parameter pack? Did Roger Rabbit exist prior to the film "Who Framed Roger Rabbit?" What attributes of a Pokemon can be improved?

[PDF] Package 'groupdata2', A similar grouping factor is created for x, to have group identifiers range from N.B. When passing num_col, the method parameter is ignored. How many levels of extreme pairing to do when balancing folds by a numerical. auto is used to automatically deduce the type but here you are asking it to be multiple different types which could make sense in a scripting language but not in a statically typed language like C++. The only way I know of to iterate through a parameter pack is to use recursion.

Description of groupdata2, Abstract. groupdata2 is a set of methods for easy grouping, windowing, folding, fold(); partition(); balance(); Extra arguments showcase Prime numbers are generated with the 'numbers' package by Hans Werner Borchers. How many levels of extreme pairing to do when balancing groups by num_col. Hi. I've been struggling for weeks about how Parameter Pack extension really works. Preface: I over-used Google and cppreference, but I still don't get it. For example:

statement folding on variadic templates parameters pack, Expression folding on a variadic template parameters pack are great and in contrast to recursive templates and should have better compilation speed. to the Google Groups "ISO C++ Standard - Future Proposals" group. Line 1 tells us there will be zero or more parameters. Line 2 declares a function with said variable number of parameters. Line 4 is where the magic happens. The fold expression states that for every parameter in the args parameter pack, combine it with the next one using operator +.

Comments
  • I guess this could also work with a bool (if only pairing isneeded) ala. : b ^= true; and then perhaps tenary operator (b ? ": '", " : "' ")
  • @darune Sure, there are other ways to express the alternation. I decided to separate the output/alternation logic from the actual token values, which the array accomplishes nicely. I dislike the implicit conversion from bool to int when indexing so I went with an actual int to toggle the state. And pre- vs postfix ++ takes extra mental cycles to verify (for me at least), while the separate 1 - can't really be misread. In short, I tried to keep this as readable as possible, but this is of course up to personal taste (or the applicable style guide). max66 condensed it much more.
  • Using a std::array instead of a native array seems a pointless complication.
  • @Deduplicator I disagree strongly, as I find std::array<const char*, 2> infinitely more readable than const char**. But again, this is my best shot at readability around some pretty obscure syntax, you can do with it what you like in your own code. All I can do is give you the data point of what I consider readable.
  • will template recursion depth be different than with a fold expression ? or will it be the same
  • @darune There is no inherent recursion with fold expressions... Fold expressions just formally expand to some expression (in that specific instantiation of the variadic template).
  • @MaxLanghof This has the advantage(?) of easy extension to more separators.
  • @Deduplicator I don't understand what you are referring to? Can you explain?
  • @Deduplicator - Not clear to me what do you mean with "extension to more separators"... anyway... this solution is very similar to the accepted one; I don't think it's more or less extensible. I suppose that is a little (little! maybe the compiler optimize in the same way) lighter because avoid the use of a std::array (that, anyway, is a light class) but (so I think is preferable the accepted answer) is less readable.
  • This requires all args to be convertible to std::strings.
  • @walnut, that is correct. If this cannot be a requirement, then you'll have to result to fold expressions/recursion