V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Stoulla
V2EX  ›  问与答

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

  •  
  •   Stoulla · 2020-11-26 21:00:58 +08:00 · 948 次点击
    这是一个创建于 1492 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    问题如下:

    采用 C++ 14 。

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

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

    • 比如, args 中含 int, 则认为传入的是 dim, 执行 funcDim()
    • 若是, args 中含 string, 则认为传入的是 name, 执行 funName().
    • 上述的 funcDim() , funcName() 是 lambda 函数,但因为觉得对问题没有帮助所以省略。

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

    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. 有没有更优雅的方案?
    3 条回复    2020-11-27 15:23:51 +08:00
    boyhailong
        1
    boyhailong  
       2020-11-27 10:14:39 +08:00
    这样定义本身就很麻烦了吧,还不如 C 里直接 void*简洁呢
    Yienschwen
        2
    Yienschwen  
       2020-11-27 15:11:54 +08:00
    你的需求不是特别清楚……所以不是很明白为什么你觉得递归解包不方便

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

    我在 [godbolt]( https://godbolt.org/z/9j9zGv) 大概看了一下,应该能说明问题。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2489 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 04:42 · PVG 12:42 · LAX 20:42 · JFK 23:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.