rabtors
rabtors

Reputation: 75

How to store arguments list to vector?

How can I store variadic constructor arguments to vector?

Example with my failed tries:

class Combo 
{
public:
   template <class... Args>
   Combo(Args... args) 
   {
      // this->keys_.push_back(args...);

      // this->keys_.push_back(args)...;

      // this->keys_.push_back(std::forward<Args>(args...));

      //for (uint8_t arg : args...)
      //  this->keys_.push_back(arg);

      // ???
   }

private:
   std::vector<uint8_t> keys_;
};

Upvotes: 4

Views: 279

Answers (4)

Chnossos
Chnossos

Reputation: 10466

template<typename... Args>
Combo(Args &&... args): keys_ { std::forward<Args>(args)... } {}

Or:

Combo(std::initializer_list<uint8_t> keys): keys_(keys) {}

Upvotes: 1

JeJo
JeJo

Reputation: 32722

In using fold expression, you might do

#include <vector>
#include <utility> // std::forward

class Combo
{
public:
   template <class... Args>
   Combo(Args&&... args) 
   {
      keys_.reserve(sizeof...(Args));  // reserve memory for unwanted reallocation
      (keys_.emplace_back(std::forward<Args>(args)), ...);
   }

private:
   std::vector<uint8_t> keys_;
};

However, that will allow one to pass types other than uint8_t and for those types which can be implicitly converted to uint8_t, an implicit conversion will take place.

This will not be the desired behaviour. Therefore I would suggest the static_assert as follows.

#include <type_traits> // std::is_same_v

template <class... Args>
Combo(Args&&... args)
{
   // to make sure that the args all are of type `uint8_t`
   static_assert((std::is_same_v<uint8_t, Args> && ...), "Args should be uint8_t");

   keys_.reserve(sizeof...(Args));  // reserve some memory for unwanted reallocation
   (keys_.emplace_back(std::forward<Args>(args)), ...);
}

this will give you now an error for the following

Combo obj{ 1, 2, 3, 4.f };
//                  ^^^^ --> float

Upvotes: 5

bipll
bipll

Reputation: 11940

  1. C++11
for(auto &&i: {args...}) keys.push_back(std::move(i));
  1. C++17
(keys.push_back(args), ...);
  1. Oh, sorry, I've missed the obvious:
template<class... Args> Combo(Args... args): keys_{uint8_t(args)...} {}

Upvotes: 5

Acorn
Acorn

Reputation: 26066

You can write:

template <class... Args>
Combo(Args... args)
{
    (keys_.push_back(args), ...);
}

Upvotes: 1

Related Questions