C++ 模板编程 - variadic template - unpack 疑问

2020-11-26 21:00:58 +08:00
 Stoulla

最近用 C++的时候遇到了对variadic template 解包的问题,在 StackOverflow 上也找了好多,但始终没形成一个好的思路,所以来 V 站求助下。

问题如下:

采用 C++ 14 。

函数接受至少一个参数,可能有多个参数,第一个参数 arg1 是确定的类型 T 。后面的参数 args 会有不同的类型, 如 int/ string /custom_class 等.

根据 args 参数不同,调用不同的函数,或者是返回 bool 类型。

想把主函数指针写成如下形式:

template <typename T, typename ... Ts>
auto funcPtr = std::function< bool (T arg1, Ts ... args)>;

请问:

  1. 这个要如何在这种 variadic functions 中进行解包呢? 网上的大多数是采用 recursive 的方式,但如果不采用 recursive 方式,如何比较简单的解包? 我认为一个比较清楚的方式是把 args 转成 tuple,即调用std::make_tuple(args ...), 但这个感觉不是很优雅,而且转换一次有效率损失。请问有什么好的方法呢?
  2. 如果这种解包不可能,我能否写三个重载函数,然后用同一个函数指针作为入口, 在运行时指向不同的函数? 即写三个函数 func(arg1) , func(arg1, int1), func(arg1, string1) 这种,然后用 funcPtr 运行时动态的绑定。
  3. 有没有更优雅的方案?
799 次点击
所在节点    问与答
3 条回复
boyhailong
2020-11-27 10:14:39 +08:00
这样定义本身就很麻烦了吧,还不如 C 里直接 void*简洁呢
Yienschwen
2020-11-27 15:11:54 +08:00
你的需求不是特别清楚……所以不是很明白为什么你觉得递归解包不方便

关于你问题的第二点,这会令你的入口函数能够在运行时接受不同类型的参数,我感觉这一点只有类似于[va_arg]( https://en.cppreference.com/w/cpp/utility/variadic/va_arg),但这样类型信息需要你预先知道,反而是静态多态容易处理这个问题。
Yienschwen
2020-11-27 15:23:51 +08:00
如果你对参数的顺序没有任何约束,那比如你要把某个`int`取出来时,你其实也不知道这个`int`在什么位置,那你用`tuple`其实也不解决问题。另外,如果你哪怕用了`tuple`,只要你小心地控制是否拷贝(比如用`tuple<const Targs& ...>`,其实大多数编译器都能优化,没有什么额外开销。

我在 [godbolt]( https://godbolt.org/z/9j9zGv) 大概看了一下,应该能说明问题。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/729627

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX