6

I have function like this:

template <typename ... Types>
void foo(const Types & ... values)
{
    // expected that 'values' is sequence like
    // '1, customvalue1, 2, customvalue2, 3,...'
}

And second function:

template <typename ... Types>
void bar(const Types & ... values)
{
    // where 'values' are any variables
    // some magic here
    foo((int_seq<sizeof...(Types)>, values)...);
}

I'd like to pass any sequence of variables to bar, so that this sequence convert to sequence like '1, value1, 2, value2, 3, value3'. So each value follows its number in base sequence. But I cannot create this 'magic code' to transform sequence on compile phase between this two state.

3
  • 2
    I assume that bar is supposed to call foo? Not call itself recursively? Commented Aug 3, 2016 at 17:19
  • have you looked at an associative array? This seems like a problem for this type of data structure Commented Aug 3, 2016 at 18:14
  • Yes, i was wrong, it's of course 'foo', not 'bar' Commented Aug 4, 2016 at 8:09

2 Answers 2

1

Not really elegant but, using tuples, std::tie, etc...

The following example should work with C++11

--- EDIT ---

Modified and unified (C++11 without C++14 elements) my first example.

There is no need of std::index_sequence (a trivial struct indSeq can be used instead) or std::make_index_sequence (the index sequence can be contructed step by step using sizeof...(I)); no need of qux() anymore.

#include <tuple>
#include <iostream>


void foo ()
 { }

template <typename T0, typename ... Types>
void foo (const T0 & v0, const Types & ... values)
 {
   std::cout << "-- " << v0 << std::endl;

   foo(values...);
 }


template <std::size_t ...>
struct indSeq
 { };

template <std::size_t ... Is, typename ... Ts1>
void baz (std::size_t, const indSeq<Is...> &, const std::tuple<Ts1...> & t)
 { foo(std::get<Is>(t)...); }

template <std::size_t ... Is, typename ... Ts1, typename T0, typename ... Ts2>
void baz (std::size_t n, const indSeq<Is...> &, const std::tuple<Ts1...> & t,
          const T0 & v0, const Ts2 & ... vs)
 { baz(n+1U, indSeq<Is..., sizeof...(Is), sizeof...(Is)+1U>(),
       std::tuple_cat(t, std::tie(n), std::tie(v0)), vs...); }

template <typename ... Types>
void bar (const Types & ... values)
 { baz (1U, indSeq<>(), std::tuple<>(), values...); }

int main()
 {
   bar(11, 22L, "33", 44.44);
   return 0;
 }

p.s.: sorry for my bad English.

Sign up to request clarification or add additional context in comments.

Comments

1

Here's a C++14 solution, but all the necessary library parts can be written in C++11 as well.

#include <iostream>
#include <tuple>
#include <utility>

template <typename ... Types>
void foo(const Types & ... values)
{
    using swallow = bool[];
    (void)swallow{ (std::cout << values << std::endl,false)... };
}

template <std::size_t N, bool = (N%2==0)>
struct pick {
    template<typename... Types>
    static std::size_t get(const std::tuple<Types...>&) { return N/2; }
};

template <std::size_t N>
struct pick<N,false> {
    template<typename... Types>
    static auto get(const std::tuple<Types...>& t) { return std::get<N/2>(t); }
};

template <std::size_t... Indices, typename ... Types>
void bar2(const std::index_sequence<Indices...>, const Types & ... values)
{
    auto x = std::tie(values...);
    foo(pick<Indices>::get(x)...);
}

template <typename ... Types>
void bar(const Types & ... values)
{
    bar2(std::index_sequence_for<Types...,Types...>(), values...);
}

int main()
{
    bar( "Hallo", 42, 1.23 );
}

Live example

It is currently zero-based, but a +1 in the right place will fix that easily. Also, it creates an intermediate std::tuple with references to the values, if performance is an issue better options might exist but since you weren't using std::forward I figured that a small performance impact might be acceptable for you.

1 Comment

I would have found making a tuple-of-2-tuples, then flattening, to be my default approach. In C++17, I could use if constexpr, tupler, a lambda and std::apply to do the call inline, which would be really fun.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.