【问题标题】:How to iterate over variadic function with std:string arguments?如何使用 std:string 参数迭代可变参数函数?
【发布时间】:2016-12-20 07:32:12
【问题描述】:
void foo(std::string arg, ...) {

   // do something with every argument

}

假设我希望能够获取每个字符串参数并在将其打印到新行之前附加一个感叹号。

【问题讨论】:

  • 简单的答案是您不能。没有允许您枚举或迭代参数的标准功能。这就是为什么 vararg 函数需要包含有关其余参数的信息的特殊参数,例如 printf 格式字符串。你可以通过传递一个额外的第一个整数参数来解决它,它的值是字符串参数的数量。或者,由于您使用 C++ 编程,您可以使用模板和 parameter packs
  • 那么有一个小问题是它是未定义的行为来传递一个可变参数函数任何不是内置类型的东西......

标签: c++ variadic


【解决方案1】:

最好的方法是使用parameters pack。例如:

#include <iostream>

// Modify single string.
void foo(std::string& arg)
{
    arg.append("!");
}

// Modify multiple strings. Here we use parameters pack by `...T`
template<typename ...T>
void foo(std::string& arg, T&... args)
{
    foo(arg);
    foo(args...);
}

int main()
{
    // Lets make a test

    std::string s1 = "qwe";
    std::string s2 = "asd";

    foo(s1, s2);

    std::cout << s1 << std::endl << s2 << std::endl;

    return 0;
}

这将打印出来:

qwe!
asd!

【讨论】:

  • 感谢 yaranov,有没有迭代的方法来做到这一点?我问是因为我想定义一个函数/api,它将字符串列表转换为单个逗号分隔的字符串。似乎带有循环的字符串流是最有效的方法。
  • 如果你有一个字符串列表,那么首先如果你需要修改字符串,那么你可以使用foo 接受列表中每个字符串的单个参数(每个项目都将被修改,因为参数foo 通过引用传递),第二个是通过使用 boost (boost.org/doc/libs/1_60_0/doc/html/boost/algorithm/join.html) 中的 join 之类的东西来连接列表中的字符串来创建一个新字符串。
【解决方案2】:

C++17

使用parameter packfold expression

#include <iostream>
#include <string>

// Modify multiple strings. Here we use parameters pack by `...T`
template<typename ...T>
void foo(T&... args)
{
    (args.append("!"),...);
}

int main()
{
    // Lets make a test

    std::string s1 = "qwe";
    std::string s2 = "asd";

    foo(s1, s2);

    std::cout << s1 << std::endl << s2 << std::endl;

    return 0;
}

【讨论】:

    【解决方案3】:

    这是一个迭代解决方案。函数调用有一点杂音,但不需要计算 varargs 的数量。

    #include <iostream>
    #include <string>
    #include <initializer_list>
    #include <functional> // reference_wrapper
    
    void foo(std::initializer_list<std::reference_wrapper<std::string>> args) {
        for (auto arg : args) {
            arg.get().append("!");
        }
    }
    
    int main() {
        // Lets make a test
    
        std::string s1 = "qwe";
        std::string s2 = "asd";
    
        foo({s1, s2});
    
        std::cout << s1 << std::endl << s2 << std::endl;
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-13
      • 2011-02-24
      • 1970-01-01
      • 2020-09-07
      • 2016-09-20
      • 2015-09-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多