2

为什么第二个例子不起作用?有没有办法让第二个示例工作,同时仍然将 lambda 或函数类型转换为介质以供以后参考?

// Types I'm using
typedef void (*ANY_FUNC)(...);
typedef void (*VOID_FUNC)();

这有效

void call_void( VOID_FUNC func) {
    ((ANY_FUNC)func)();
};

// ...

call_void([]() { /* do something */ });

这不

template <typename fn>
void call_any( fn func ) {
    ((ANY_FUNC)func)();
};

// ...

call_any([]() { /* do something */ });

请忽略这样一个事实,即您永远不需要使用第二个示例。它仅用于演示(相对代码)。

这两个示例都使用函数指针而不是 lambda。

4

4 回答 4

2

只要您声明一个模板,您就可以直接使用传入的函数对象。此外,您应该将函数参数声明为引用而不是按值:

template <typename fn>
void call_any(fn&& func) {
    func();
};

如果你想用参数调用一个函数,你可以这样做:

template <typename fn, typename... Args>
void call_any_many(fn&& func, Args&&... args) {
    func(std::forward<Args>(args)...);
};

使用示例:

int main ()
{
    call_void([]() { std::cout << "Hello, void World!" << std::endl; });
    call_any([]() { std::cout << "Hello, any World!" << std::endl; });
    call_any_many([](int x) { std::cout << "Hello, any many World-" << x << "!" << std::endl; }, 1234);

    return 0;
}

但是如果你的意图是存储一些函数指针而不是直接调用它们,我建议使用std::functionfrom <functional>header。您可以从这里查看一些信息和示例:http: //en.cppreference.com/w/cpp/utility/functional/function

例如:

#include <iostream>
#include <functional>

int main ()
{
    std::function<void()> anyf = []() { std::cout << "Hello, any World!" << std::endl; };
    std::function<void(int)> intf = [](int x) { std::cout << "Hello, any many World-" << x << "!" << std::endl; };

    anyf();
    intf(1234);

    return 0;
}
于 2012-12-29T11:22:27.957 回答
0

我认为它们中的任何一个都不能真正起作用,除非在某些编译器上是偶然的。

与 lambda 的区别在于它可以转换为函数指针,但它不是一个。模板版本会注意到这种差异,并且fn不会被推断为VOID_FUNC.

于 2012-12-29T09:51:03.127 回答
0

Lambda 可以隐式转换为函数指针(但前提是它们不捕获任何内容),因此只需将 call_any 的参数更改为函数指针:

void call_any(ANY_FUNC func)
{
    (*func)();
}

您需要使用适当类型的 lambda 调用它:

call_any([](...) { /* ... */ });

但是可变长度参数列表(又名 varargs)很糟糕,因为它们是非类型安全的。与函数指针相同:它们是非面向对象的。您应该考虑一种替代机制,可能涉及可变参数模板和多态性(虚拟方法)

于 2012-12-29T09:59:52.720 回答
0

第一个是将 lambda 转换为具有相应参数和返回类型的函数指针,然后将其转换为 vararg 函数,而第二个是尝试将 lambda 直接转换为 vararg 函数(即,没有相应参数类型的函数)。

第一个示例中的两次转换是允许的*,但第二个示例中的一次转换是不允许的。

*请注意,用于在函数指针类型之间转换的强制转换符号最终会像reinterpret_cast以下状态一样工作:“函数指针可以显式转换为不同类型的函数指针。通过指向函数的指针调用函数的效果与函数定义中使用的类型不同的类型(8.3.5)未定义。” 因此,第一个示例代码具有未定义的行为。

于 2012-12-29T10:03:13.347 回答