I am trying to make a function that adds an unknown amount of objects to a vector. I am trying to accomplish it here by just passing ints, but I cannot get it to work. Does any one know how this can be done?
Code
#include <iostream>
#include <vector>
class Entity
{
public:
std::vector<int> Ints;
template <typename T, typename ... pack>
void AddToVector(T first, pack ... argPack)
{
Ints.push_back(argPack...);
for(auto& i : Ints)
std::cout << i << "\n" << std::endl;
};
};
int main()
{
Entity e1;
e1.AddToVector(1, 2, 3, 4, 5);
return 0;
}
Error:
main.cpp: In instantiation of ‘void Entity::AddToVector(T, pack ...) [with T = int; pack = {int, int, int, int}]’:
main.cpp:32:33</span>: required from here
main.cpp:20:9: error: no matching function for call to ‘std::vector::push_back(int&, int&, int&, int&)’
CodePudding user response:
In C 11 and C 14, You can use something like this:
private:
void Internal_AddToVector()
{
}
template <typename T, typename ... pack>
void Internal_AddToVector(T first, pack... argPack)
{
Ints.push_back(first);
Internal_AddToVector(argPack...);
}
public:
template <typename ... pack>
void AddToVector(pack ... argPack)
{
Internal_AddToVector(argPack...);
for(auto& i : Ints)
std::cout << i << "\n" << std::endl;
}
Alternatively:
public:
template <typename ... pack>
void AddToVector(pack ... argPack)
{
for (auto& elem : {argPack...})
Ints.push_back(elem);
for(auto& i : Ints)
std::cout << i << "\n" << std::endl;
}
In C 17 and later, you can use a fold expression instead:
public:
template <typename ... pack>
void AddToVector(pack... argPack)
{
(Ints.push_back(argPack), ...);
for(auto& i : Ints)
std::cout << i << "\n" << std::endl;
}
CodePudding user response:
Ints.push_back(argPack...);
If, for example, there are for parameters this becomes:
Ints.push_back(1, 2, 3, 4);
If you refer to the specifications for push_back()
you will find out that it takes exactly one parameter, and not four. Hence the compilation error.
The fact that your template is declares thusly:
template <typename T, typename ... pack>
void AddToVector(T first, pack ... argPack)
this strongly suggests that your assignment's intention is for the template function to push_back()
one value at a time:
Ints.push_back(first);
And then recursively invoke itself:
AddToVector(argPack...);
That, of course, would not be very optimal, however I'm optimistic that modern C compilers will be able to optimize most of this away.
But there is still one more detail that must be taken care of: an empty parameter pack. This is a guaranteed eventuality and overload resolution will fail. Therefore you must provide a do-nothing overload, for that eventuality:
void AddToVector()
{
}
CodePudding user response:
[[maybe_unused]] int dummy[sizeof...(pack)] = {(Ints.push_back(argPack), 0)...};
or
([&]{Ints.push_back(argPack);}(), ...);
will do the job. I'm not sure what standard these are supported onwards.
CodePudding user response:
You want to push back all the values. push_back
only accepts one argument. If you're using C 17 or greater, use a fold expression:
class Entity
{
public:
std::vector<int> Ints;
template <typename T, typename ... pack>
void AddToVector(T first, pack ... argPack)
{
(Ints.push_back(argPack), ...);
for(auto& i : Ints)
std::cout << i << "\n" << std::endl;
};
};
int main()
{
Entity e1;
e1.AddToVector(1, 2, 3, 4, 5);
return 0;
}
Otherwise, a for loop:
class Entity
{
public:
std::vector<int> Ints;
template <typename T, typename ... pack>
void AddToVector(T first, pack ... argPack)
{
for (auto& elem : {argPack...}) Ints.push_back(elem);
for(auto& i : Ints)
std::cout << i << "\n" << std::endl;
};
};
int main()
{
Entity e1;
e1.AddToVector(1, 2, 3, 4, 5);
return 0;
}