c++ - 将 STL 容器扩展为可变参数模板

标签 c++ templates c++11 stl variadic-templates

为了保持通用和直接,假设我有一个整数 std::vector,例如:

std::vector<int> v;

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

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

然后我们希望使用恰好 3 个整数调用“pass”。细节并不重要。我想知道的是,以下是否可行:

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

在哪里...像可变参数模板一样使用?本质上,我是在问我是否可以

  1. 将 std::vector 或其他 STL 容器扩展为具有 n 个元素的可变参数模板
  2. 和/或按顺序将这些值直接传递给被调用的函数

这在 C++11 中可行吗?请注意,我需要它才能在 MSVC v120/VS2013 上工作。

最佳答案

这绝对是可能的,但你无法确定在编译时这样做是否安全。正如 WhozCraig 所说,这是因为 vector 缺少编译时大小。

我仍在尝试赢得模板元编程的翅膀,所以我可能做了一些不寻常的事情。但这里的核心思想是让一个函数模板递归地使用 vector 中的下一项调用自身,直到它用所需的参数构建了一个参数包。一旦有了它,就很容易将它传递给有问题的函数。

这里核心的实现在apply_first_n , 它接受一个目标 std::function<R(Ps...)> ,和一个 vector ,以及一个 Ts... 的参数包.当Ts...短于 Ps...它建立了包装;一旦大小相同,就会将其传递给函数。

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); .在live example , make_fn只是转换为 std::function更容易,而且ProcessInts是一个方便的测试函数。

我很想知道如何避免使用 std::function ,并修复存在的任何其他严重低效问题。但我想说这证明了这是可能的。


作为引用,我进一步采用了上述方法,处理 set , vector , tuple , 和 initializer_list ,以及其他匹配正确接口(interface)的。删除 std::function似乎需要 func_info特征类,以及几个重载。所以虽然这个 extended live example肯定更一般,我不确定我会称之为更好。

关于c++ - 将 STL 容器扩展为可变参数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23946300/

相关文章:

c++ - 使用在模板化类型名中定义的 typedef

c++ - 使用 std::enable_if 作为函数参数与模板参数有什么区别?

C++17 使用选定的构造函数在堆栈中构造数组(每个数组条目的构造函数参数值相同)

c++ - 二值图像中不同区域的数量 (c++)

c++ - 指向对象数据成员的 shared_ptr 是否使数据成员在对象的生命周期之后保持事件状态?

C++:静态函数的模板?

c++ - Boost 程序选项遍历 variables_map

c++ - 将每种类型包装在模板类中的可变参数模板中

C++ getline 方法不起作用

c++ - Windows CE 7.0 应用程序无法分步调试