【问题标题】:String argument after parameter pack参数包后的字符串参数
【发布时间】:2021-06-05 15:59:22
【问题描述】:

我想编写一个函数write,它可以接受多个任意类型的参数,并将它们打印到stdout。 但我也想传入一个分隔符作为最后一个参数。

template <typename... T>
void write(T &&...args, string delimiter) { // compilation error
    ((cout << args << delimiter),...);
}

用法:

write(1, ""); // single element with empty delimeter
write(1, "one", " "); // space as delimeter
write(1, "one", ","); // comma as delimeter 

目前,自动类型推断失败,因为 C++ 期望参数包是最后一个参数。

我怎样才能做到这一点?

【问题讨论】:

  • 您希望write("a","b","c") 会发生什么?它可以以任何一种方式解析,“c”要么被推导出为分隔符,要么作为三参数包中的最后一个。参数包仅在它们是 last 函数参数时才有效。
  • write(T&amp;&amp; ...args) 具有硬编码的"," 定界符,以及write_using_delim(string delimiter, T&amp;&amp; ..args) 调用者提供定界符作为第一个参数。
  • @SamVarshavchik 好点,可以说我可以删除默认值。所以最后一个参数将始终是字符串,它将是分隔符,如何实现呢?
  • @cigien 问题已编辑
  • @SamVarshavchik write("a", "b", "c") 在您拥有 write(T... args, std::string foo) 时与拥有 write(std::string foo, T... args) 时完全相同。无论顺序是什么,您首先会获得不能成为包一部分的参数 (foo),然后其余的将成为包的一部分。老实说,我不知道为什么 pack 必须是最后一个论点,可能委员会对此有更好的论点。

标签: c++ parameter-passing variadic-functions


【解决方案1】:

blog article 中有一个不错的技术,您可以使用它。

修改write 只接受一个参数包

template <typename... Ts>
void write(Ts && ...args) 
{ 
    write_indirect(std::forward_as_tuple(args...),
                   std::make_index_sequence<sizeof...(args) - 1>{});
}

现在write_indirect 只需将参数包作为一个元组,连同参数的索引作为模板参数。然后它使用get 提取最后一个参数,并将其作为第一个参数传递给write_impl。剩余的参数从元组中解包,并作为第二个参数传递

template<typename... Ts, size_t... Is>
void write_indirect(std::tuple<Ts...> args, std::index_sequence<Is...>)
{
    auto constexpr Last = sizeof...(Ts) - 1;
    write_impl(std::get<Last>(args), std::get<Is>(args)...);
}  

现在write_impl 只是您原来的write 函数,但它以分隔符作为第一个参数

template <typename... Ts>
void write_impl(std::string delimiter, Ts && ...args) 
{   
    ((std::cout << args << delimiter),...);
}

这是demo

【讨论】:

  • 我的意思是这确实有效,但它的工作量太大了。 C++ 应该有更好的东西,我认为命名参数可以使实现更容易。
猜你喜欢
  • 1970-01-01
  • 2021-09-07
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多