传递变元函数作为参数

Passing a variadic function as argument

本文关键字:参数 函数      更新时间:2023-10-16

考虑一下这个工作代码:

#include <iostream>
#include <utility>
#include <array>
template <typename... Args>
void foo (Args&&... args) {
    const auto v = {args...};
    for (auto x : v) std::cout << x << ' ';     std::cout << 'n';
}
template <typename> struct Foo;
template <std::size_t... Is>
struct Foo<std::index_sequence<Is...>> {
    template <typename Container>
    static void execute (const Container& v) {
        foo(v[Is]...);
    }
};
template <std::size_t N>
void fooArray (const std::array<int, N>& a) {
    Foo<std::make_index_sequence<N>>::execute(a);
}
int main() {
    fooArray<6>({0,1,2,3,4,5});  // 0 1 2 3 4 5
}

我现在想将Foo结构概括为:

#include <iostream>
#include <utility>
#include <array>
template <typename... Args>
void foo (Args&&... args) {
    const auto v = {args...};
    for (auto x : v) std::cout << x << ' ';     std::cout << 'n';
}
template <typename> struct Foo;
template <std::size_t... Is>
struct Foo<std::index_sequence<Is...>> {
    template <typename Container, typename F>  // *** Modified
    static void execute (const Container& v, F f) {
        f(v[Is]...);
    }
};
template <std::size_t N>
void fooArray (const std::array<int, N>& a) {
    Foo<std::make_index_sequence<N>>::execute(a, foo);
}
int main() {
    fooArray<6>({0,1,2,3,4,5});
}

但我得到了一个编译错误(来自GCC 4.9.2(,无法推导F。我该如何做到这一点?

foo是一个重载族,因此foo是不明确的
(甚至foo<int, int>也是,因为它也可能具有附加类型(。

您可以强制执行以下预期类型的功能:

template <std::size_t... Is>
struct Foo<std::index_sequence<Is...>> {
    template <typename Container>
    static void execute (const Container& v, void (*f)(decltype(v[Is])&...)) {
        f(v[Is]...);
    }
};

实例

另一种选择是将函数foo封装到一个类中:

class FooCaller
{
public:
    template <typename... Args>
    void operator () (Args&&... args) const {
        const auto v = {args...};
        for (auto x : v) std::cout << x << ' ';     std::cout << 'n';
    }
};

并保持您的实施:

实时演示

模板不是一个单一的东西。不能将模板函数作为函数或对象传递。现在,重载集的名称(比如foo(可以在特定上下文中解析为模板函数的单个实例(在您调用它的地方,或者将它转换为函数指针(,这可能就是欺骗您的原因。

如果你想把整个过载集作为一个对象来处理,你可以通过来近似它

struct foo_f{
  template<class...Args>
  auto operator()(Args&&...args)const->
  decltype(foo(std::declval<Args>()...))
  { return foo(std::forward<Args>(args)...); }
};

并且现在CCD_ 7的实例将CCD_。用foo_f{}代替foo

在C++14中,或者:

[](auto&&...args)->decltype(auto){return foo(decltype(args)(args)...);}

是一个lambda,其行为与上面的foo_f非常相似。