Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

converting parameter pack into a vector

Tags:

c++

c++11

c++14

I am trying to understand variadic templates in C++ and I am lost in the following example: Imagine a function foo(T, T, T, T) which takes variadic number of arguments of the same type T and converts them into a vector. Any idea how to implement one?

It should work like this

foo<int>(1,2,3,4) returns std::vector<int> x{1,2,3,4}
foo<double>(0.1,0.2,0.3) returns std::vector<double> x{0.1,0.2,0.3}
like image 454
Bociek Avatar asked Sep 08 '26 09:09

Bociek


2 Answers

If the T values are known at compile-time, you can pass them as template parameters and write something like this:

template<typename T, T ... Is>
void foo() {
   std::vector<T> x { { Is.. } };
   
   for( auto xx:x )
      std::cout << xx << std::endl;
}

That is called like this:

foo<int, 2, 3, 5, 7>();

Otherwise, you have to pass them as arguments; something like this:

template <typename T, typename ... ARGS>
void foo (ARGS const & ... args) {    
   std::vector<T> x { { args... } };

   for( auto xx:x ) 
      std::cout << xx << std::endl;
}

That is called like this:

foo<int>(2, 3, 5, 7);

or also (deducing the type T from the first argument):

template <typename T, typename ... ARGS>
void foo (T const & arg0, ARGS const & ... args) {    
   std::vector<T> x { { arg0, args... } };

   for( auto xx:x ) 
      std::cout << xx << std::endl;
}

That is called like this:

foo(2, 3, 5, 7);

-- EDIT --

The OP writes:

It should work like this

foo<int>(1,2,3,4) returns std::vector<int> x{1,2,3,4}
foo<double>(0.1,0.2,0.3) returns std::vector<double> x{0.1,0.2,0.3}

So I suppose you can simply write:

template <typename T, typename ... ARGS>
std::vector<T> foo (ARGS const & ... args)
 { return { args... }; }
like image 198
max66 Avatar answered Sep 11 '26 08:09

max66


In foo, I create a vector with the exact capacity to hold all the parameters and then recursively handle each parameter by pushing it to the back of the vector, which is passed to a helper template function called append_to_vector.

#include<vector>    
namespace test2
{
    template<typename TN>
    void append_to_vector(std::vector<TN>& outputvector, const TN& elem)
    {
        outputvector.push_back(elem);
    };

    template<typename T0, typename ...T1toN>
    void append_to_vector(std::vector<T0>& outputvector, const T0& elem, T1toN... elems)
    {
        outputvector.push_back(elem);
        append_to_vector(outputvector, elems...);
    };

    template<typename T, typename ...T0toN>
    auto foo(const T0toN... elems)
    {
        std::vector<T> vec;
        vec.reserve(sizeof...(elems));
        append_to_vector(vec, elems...);
        return vec;
    };
}



int main()
{
   std::vector<int> vec;
   auto vec1 = test2::foo<int>(1,2,3,4);
   auto vec2 = test2::foo<double>(0.1,0.2,0.3,0.4);
   return 0;
}
like image 26
T33C Avatar answered Sep 11 '26 08:09

T33C



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!