将STL容器扩展为可变参数模板 [英] Expanding an STL container into a variadic template

查看:93
本文介绍了将STL容器扩展为可变参数模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为使事情通用且简单,请说我有一个整数的std :: vector,例如:

To keep things generic and straightforward, say that I have a std::vector of integers, such as:

std::vector<int> v;

现在,我想知道的是,是否可以取n(其中n是一个已知的常数在编译时)从v值并将它们传递给任意函数?我知道这对可变参数模板是可行的:

Now, what I am wondering is, is it possible to take n (where n is a constant known at compile time) values from v and pass them to an arbitrary function? I know that this is doable with variadic templates:

template<typename... T>
void pass(void (*func)(int, int, int), T... t) {
  func(t...);
}

然后我们希望 pass正好用3个整数调用。细节无关紧要。我想知道的是,以下某种方式可行:

And then we hope 'pass' is called with exactly 3 integers. The details don't matter so much. What I am wondering is, is the following somehow doable:

void pass(void (*func)(int, int, int), std::vector<int> &t) {
  auto iter = t.begin();
  func((*iter++)...);
}

在何处……像可变参数模板一样使用?本质上,我在问我是否可以

Where ... is being used like a variadic template? Essentially, I'm asking if I can


  1. 将std :: vector或其他STL容器扩展为具有n个元素的可变参数模板

  2. 和/或有序地将这些值直接传递给被调用的函数

这可能吗用C ++ 11?注意,我需要在MSVC v120 / VS2013上使用它。

Is this possible with C++11? Noting that I need this to work on MSVC v120/VS2013.

推荐答案

肯定有可能,但是您不能确定这样做的安全性它在编译时。正如WhozCraig所说,这是因为向量缺少编译时大小。

It's definitely possible, but you cannot determine the safety of doing it at compile time. This is, as WhozCraig says, because the vector lacks a compile-time size.

我仍在尝试赚取模板元编程的翅膀,所以我可能已经做了事情有点不寻常。但是这里的核心思想是让函数模板递归调用向量中的下一个项目,直到它建立了具有所需参数的参数包为止。一旦有了它,就很容易将其传递给所讨论的函数。

I'm still trying to earn my template meta programming wings, so I may have done things a little unusually. But the core idea here is to have a function template recursively invoke itself with the next item in the vector until it has built up a parameter pack with the desired parameters. Once it has that, it's easy to pass it to the function in question.

此处的核心实现在 apply_first_n ,它接受目标 std :: function< R(Ps ...)> ,向量和 Ts ... 。当 Ts ... 短于 Ps ... 时,它构成了背包;

The implementation of the core here is in apply_first_n, which accepts a target std::function<R(Ps...)>, and a vector, and a parameter pack of Ts.... When Ts... is shorter than Ps... it builds up the pack; once it's the same size, it passes it to the function.

template <typename R, typename... Ps, typename... Ts>
typename std::enable_if<sizeof...(Ps) == sizeof...(Ts), R>::type
apply_first_n(std::function<R(Ps...)> f, const std::vector<int> &v, Ts&&... ts)
{
    if (sizeof...(Ts) > v.size())
        throw std::out_of_range("vector too small for function");
    return f(std::forward<Ts>(ts)...);
}

template <typename R, typename... Ps, typename... Ts>
typename std::enable_if<sizeof...(Ps) != sizeof...(Ts), R>::type
apply_first_n(std::function<R(Ps...)> f, const std::vector<int> &v, Ts&&... ts)
{
    const int index = sizeof...(Ps) - sizeof...(Ts) - 1;
    static_assert(index >= 0, "incompatible function parameters");
    return apply_first_n(f, v, *(std::begin(v) + index), std::forward<Ts>(ts)...);
}

您可以用 apply_first_n(std :: function< int(int,int)>(f),v); 。在实时示例中, make_fn 只是使转换为 std :: function 更容易,而 ProcessInts 是方便的测试功能。

You call this with, e.g., apply_first_n(std::function<int(int, int)>(f), v);. In the live example, make_fn just makes the conversion to std::function easier, and ProcessInts is a convenient testing function.

我很想弄清楚如何避免使用 std :: function ,并修复存在的任何其他效率低下的问题。

I'd love to figure out how to avoid the use of std::function, and to repair any other gross inefficiencies that exist. But I'd say this is proof that it's possible.

作为参考,我进一步采用了上述方法,处理了 set vector 元组 initializer_list ,以及与正确接口匹配的其他文件。删除 std :: function 似乎需要 func_info traits类,以及一些重载。因此,尽管扩展的实时示例肯定更笼统,但我不确定我是否愿意叫它更好。

For reference, I took the above approach further, handling set, vector, tuple, and initializer_list, as well as others that match the right interfaces. Removing std::function seemed to require the func_info traits class, as well as several overloads. So while this extended live example is definitely more general, I'm not sure I'd call it better.

这篇关于将STL容器扩展为可变参数模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆