[英]Passing a variadic function as argument
Consider this working code: 考虑以下工作代码:
#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
}
I want to now generalize the Foo
struct like so: 我现在想像这样概括
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});
}
But I get a compile error (from GCC 4.9.2) that F cannot be deduced. 但是我收到了一个编译错误(来自GCC 4.9.2),无法推导出F。 How do I achieve this?
我该如何实现?
foo
is a family of overloads, and so the foo
is ambiguous. foo
是重载族,因此foo
是模棱两可的。
(even foo<int, int>
is, as it may have additional type too). (即使
foo<int, int>
也是如此,因为它也可能具有其他类型)。
You may force expected type function as follow: 您可以如下强制使用预期的类型函数:
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]...);
}
};
An alternative is to wrap function foo
into a class: 另一种方法是将函数
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';
}
};
and keep your implementation: 并保持您的实施:
A template is not a single thing. 模板不是一回事。 You cannot pass a template function as a function or an object.
您不能将模板函数作为函数或对象传递。 Now the name of an overload set (say,
foo
) can resolve to a single instance of a template function in particular contexts (where you call it, or convert it to a function pointer), which is probably what fooled you. 现在,重载集的名称(例如
foo
)可以在特定上下文(在其中调用它或将其转换为函数指针)中解析为模板函数的单个实例,这很可能是骗了您的。
If you want to work with an entire overload set as an object, you can approximate it via: 如果要使用整个过载集作为对象,则可以通过以下方式对其进行近似:
struct foo_f{
template<class...Args>
auto operator()(Args&&...args)const->
decltype(foo(std::declval<Args>()...))
{ return foo(std::forward<Args>(args)...); }
};
and now an instance of foo_f
approximates the overload set of foo
as a single object. 现在
foo_f
的实例将foo
的重载集近似为单个对象。 Pass foo_f{}
in place of foo
. 传递
foo_f{}
代替foo
。
In C++14, alternatively: 在C ++ 14中,也可以:
[](auto&&...args)->decltype(auto){return foo(decltype(args)(args)...);}
is a lambda that behaves much like foo_f
above. 是一个lambda,其行为与上面的
foo_f
非常相似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.