5
#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

3 Answers 3

6

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...);


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

2 Comments

Shouldn't the following be the breaking method?: void CTest::AddStringsToVector(const std::string &First) { m_stringsvec.push_back(First); }
@HappyCoder The above it's equally good, will break the recursion when Args = [].
3

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;
        }
    }

1 Comment

@Jeka: explanation added.
1

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;
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.