【问题标题】:How to store parameters from variadic template member function into vector?如何将可变参数模板成员函数中的参数存储到向量中?
【发布时间】:2015-12-29 06:05:37
【问题描述】:
#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");
}

仅在我传递两个参数时有效:

test.AddStringsToVector("test1","test2");

如果我传递除两个以外的任意数量的参数,我会收到错误。

例如:

test.AddStringsToVector("test1","test2","test3");

错误: 严重性代码 描述 项目文件行 错误 C2661 'std::vector>::push_back': 没有重载函数需要 2 论据

【问题讨论】:

    标签: c++


    【解决方案1】:

    递归调用函数。

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

    【讨论】:

    • 不应该是下面的破解方法吗?:void CTest::AddStringsToVector(const std::string &amp;First) { m_stringsvec.push_back(First); }
    • @HappyCoder 上面一样好,Args = []时会破坏递归。
    【解决方案2】:

    非递归方法:

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

    真正的东西在那里:

    int dummy[] = { 0, (m_stringsvec.push_back(args), 0)...};
    

    (foo(), 0) 使用逗号运算符。完成第一部分(我们想要的工作)并评估为0

    通过可变参数扩展,它变成(m_stringsvec.push_back(args), 0)...

    将整体放入初始化列表中以进行担保顺序评估。

    在 C++17 中,使用折叠表达式会更简单:

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

    【讨论】:

    • @Jeka:已添加解释。
    【解决方案3】:

    另一个非递归选项(警告,大脑编译):

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-20
      • 1970-01-01
      • 2013-05-27
      • 1970-01-01
      • 1970-01-01
      • 2019-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多