#include <Windows.h>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class CTest
{
public:
template<typename... Args>
void AddStringsToVector(const std::string &First, Args&... args);
private:
std::vector<std::string> m_stringsvec;
};
template<typename... Args>
void CTest::AddStringsToVector(const std::string &First, Args&... args)
{
m_stringsvec.push_back(First);
m_stringsvec.push_back(args...);
for (auto &i : m_stringsvec)
std::cout << i << std::endl;
}
void main()
{
CTest test;
test.AddStringsToVector("test1","test2","test3");
system("pause");
}
only works when i pass two parameters:
test.AddStringsToVector("test1","test2");
If I pass any number of parameters other then two I get an error.
For example:
test.AddStringsToVector("test1","test2","test3");
Error: Severity Code Description Project File Line Error C2661 'std::vector>::push_back': no overloaded function takes 2 arguments
Recursively call the function .
void CTest::AddStringsToVector()//function to break recursion
{
}
template<typename... Args>
void CTest::AddStringsToVector(const std::string &First, Args&... args)
{
m_stringsvec.push_back(First);
AddStringsToVector(args...);
}
A non-recursive method:
class CTest
{
public:
template<typename... Args>
void AddStringsToVector(const std::string &first, const Args&... args)
{
m_stringsvec.push_back(First);
int dummy[] = { 0, (m_stringsvec.push_back(args), 0)...}; // all magic is here
(void) dummy; // Avoid unused variable warning.
for (const auto &s : m_stringsvec) {
std::cout << i << std::endl;
}
}
private:
std::vector<std::string> m_stringsvec;
};
The real stuff is there:
int dummy[] = { 0, (m_stringsvec.push_back(args), 0)...};
(foo(), 0)
uses comma operator. That do the first part (the job we want) and evaluate as 0
.
With variadic expansion, it becomes (m_stringsvec.push_back(args), 0)...
.
put the whole in initializer list to guaranty order evaluation.
In C++17, it would be even simpler with folding expression:
template<typename... Args>
void AddStringsToVector(const std::string &first, const Args&... args)
{
m_stringsvec.push_back(First);
(m_stringsvec.push_back(args), ...); // Folding expression
for (const auto &s : m_stringsvec) {
std::cout << i << std::endl;
}
}
Another non-recursive option (warning, brain compile):
struct swallow { template <typename ...T> swallow(T&& ...) noexcept { } };
class CTest
{
public:
template<typename... Args>
void AddStringsToVector(const std::string &first, const Args&... args)
{
m_stringsvec.push_back(First);
swallow{(m_stringsvec.push_back(args), 0)...};
for (const auto &s : m_stringsvec) {
std::cout << i << std::endl;
}
}
private:
std::vector<std::string> m_stringsvec;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With