c++ - 如何在 C++ 中传递参数包?

标签 c++ c++11 templates variadic-templates template-meta-programming

考虑以下示例:

template <class T> class method_traits;
template <class T, class Ret, class... Arg> class method_traits<Ret(T::*)(Arg...)> {
public:
    using type = Arg; // this does not work
};

template <class T> using argument_types = typename method_traits<T>::type;

template <class T> class Node {
    T t;
public:
    Node(Input<argument_types<decltype(&T::process)>>... inputs) { // how do I make this work?
        ...
    }
};

Node<T> 的构造函数的参数取决于方法的参数 T::process .所以如果类型 T有一个方法 process签名 float process(float a, int b) Node<T> 构造函数的签名应如下所示:Node(Input<float> a, Input<int> b) .

如何从 T::process 中提取参数包?在 Node 的构造函数上使用它?

最佳答案

显然你不能用这种方式保存类型列表

    using type = Arg;

哪里Arg是类型的可变列表。

但是你可以将它们保存在一个类型容器中并且std::tuple也可以做到这一点。所以我建议修改method_traits特化如下

template <typename T>
struct method_traits;

template <typename T, typename Ret, typename... Args>
struct method_traits<Ret(T::*)(Args...)>
 { using tTypes = std::tuple<Args...>; };

并重写argument_types拦截 std::tuple

template <typename T>
using tTypes = typename method_traits<T>::tTypes;

现在您可以使用默认模板值和偏特化技巧定义节点

template <typename T, typename TArgs = tTypes<decltype(&T::process)>>
struct Node;

这样,实例化了一个Node<T>对象,你有效地得到一个 Node<T, tTypes<decltype(&T::process)>那是一个Node<T, std::tuple<Args...>>与通缉Args... .

因此,您可以简单地定义以下 Node 的偏特化如下

template <typename T, typename ... Args>
struct Node<T, std::tuple<Args...>>
 {
   T t;

   Node (Input<Args> ... inputs)
    { /* do something */ }
 };

下面是一个完整的工作示例

#include <tuple>
#include <type_traits>

template <typename T>
struct tWrapper
 { using type = T; };

template <typename T>
using Input = typename tWrapper<T>::type;

template <typename T>
struct method_traits;

template <typename T, typename Ret, typename... Args>
struct method_traits<Ret(T::*)(Args...)>
 { using tTypes = std::tuple<Args...>; };

template <typename T>
using tTypes = typename method_traits<T>::tTypes;

template <typename T, typename TArgs = tTypes<decltype(&T::process)>>
struct Node;

template <typename T, typename ... Args>
struct Node<T, std::tuple<Args...>>
 {
   T t;

   Node (Input<Args> ... inputs)
    { /* do something */ }
 };

struct foo
 {
   float process (float a, int b)
    { return a+b; }
 };

int main ()
 {
   Node<foo> nf(1.0f, 2);
 }

-- 编辑 --

正如 Julius(和 OP 本身)所指出的,此解决方案需要一个具有默认模板值的附加模板类型。

在这种简化的情况下,这不是问题,但我可以想象无法添加此额外模板参数的情况(例如:如果 Node 收到模板参数的可变列表)。

在这些情况下,Julius 提出了一种方法,使解决方案稍微复杂一点,但可以避免为 Node 添加额外的模板参数。 : 添加一个模板基类,接收 TArgs参数,并与构造函数继承一起使用。

即:定义一个NodeBase如下

template <typename, typename>
struct NodeBase;

template <typename T, typename ... Args>
struct NodeBase<T, std::tuple<Args...>>
 {
   T t;

   NodeBase (Input<Args> ...)
    { /* do something */ }
 };

不需要额外的模板参数,对于Node ,可以简单地写成

template <typename T>
struct Node
   : public NodeBase<T, tTypes<decltype(&T::process)>>
 { using NodeBase<T, tTypes<decltype(&T::process)>>::NodeBase; };

朱利叶斯遵循这个想法,准备了a solution那(恕我直言)更好更有趣。

关于c++ - 如何在 C++ 中传递参数包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46876119/

相关文章:

c++ - 在 C++ 中模拟编译时反射

c++ - 可变参数模板和 C 数组

c++ - 在 C++ 中模板化一个函数

c++ - std::condition_variable 可预测的虚假唤醒?

c++ - 用于 C++ 的 openmpi 库

c++ - 在类似功能的 reduce 函数中转发和返回类型

c++ - C2516 在 Visual Studio 2013 中从 lambda 继承时出错

c++ - 将 std::forward 作为默认参数传递?

c++ - 模板类型的模板特化

c++ - 模板函数内的静态变量