【问题标题】:Apply function on each element in parameter pack对参数包中的每个元素应用函数
【发布时间】:2017-12-16 18:46:22
【问题描述】:

我有以下专门化的模板函数:

// Pass the argument through ...
template<typename T, typename U=T>
U convert(T&& t) {
  return std::forward<T>(t);
}

// ... but convert std::strings
const char* convert(std::string s) {
  return s.c_str();
}

如果我有一个可变参数模板函数,例如:

template<typename ... Args>
void doSomething(Args ... args) {
  // Convert parameter pack using convert function above
  // and call any other variadic templated function with
  // the converted args.
}

有没有办法像评论中那样使用convert函数转换参数包?

我最初的目标是能够在类似 printf 的函数中将 std::string 传递给“%s”,而无需先手动调用字符串上的 .c_str()。但我也很感兴趣,如果这可以通过简单的方式完成,我的尝试到目前为止都失败了。

【问题讨论】:

  • 顺便说一句,您的 doSomething 不接受转发引用,而 convert 暗示它应该接受。 convert(std::string) 也返回一个悬空指针。所以你可能想做一些改变。
  • @StoryTeller 如果我按照建议只想打印它,我认为指针没问题,因为我不打算保留它?
  • s 是本地转换。怎么会没事?
  • @StoryTeller 好的,我看到字符串是按值获取的,我可以改用引用。

标签: c++ templates metaprogramming variadic-templates


【解决方案1】:
template<typename ... Args>
void doSomething(Args ... args) {
  something(convert(args)...);
}

其中something(convert(args)...)parameter pack expansion,扩展为:

// pseudocode
something(convert(arg0), convert(arg1), convert(arg2), ...)

顺便说一句,您可能希望通过转发引用来获取args,以避免不必要的复制并正确传播左值引用

template<typename... Args>
void doSomething(Args&& ... args) {
  something(convert(std::forward<Args>(args))...);
}

【讨论】:

  • 我认为值得注意的是 something(convert(arg0), convert(arg1), convert(arg2), ...) 不能保证从左到右的顺序执行 convert() 。我认为使用 initalizer-lists 会强制从左到右执行:see here
猜你喜欢
  • 2016-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-28
  • 1970-01-01
相关资源
最近更新 更多