消除对采用 std::functions 的函数的调用的歧义

发布于 2024-09-30 17:09:48 字数 399 浏览 2 评论 0原文

下面的代码无法在 gcc 4.5 上编译,因为对 foo 的调用不明确。消除歧义的正确方法是什么?

#include <iostream>
#include <functional>
using namespace std;

void foo(std::function<void(int, int)> t)
{
    t(1, 2);
}

void foo(std::function<void(int)> t)
{
    t(2);
}

int main()
{
    foo([](int a, int b){ cout << "a: " << a << " b: " << b << endl;});
}

The code below doesn't compile on gcc 4.5 because the call to foo is ambiguous. What is the correct way to disambiguate it?

#include <iostream>
#include <functional>
using namespace std;

void foo(std::function<void(int, int)> t)
{
    t(1, 2);
}

void foo(std::function<void(int)> t)
{
    t(2);
}

int main()
{
    foo([](int a, int b){ cout << "a: " << a << " b: " << b << endl;});
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

网白 2024-10-07 17:09:48

最好的方法是显式创建正确类型的 std::function 对象,然后将该对象传递给函数:

std::function<void(int, int)> func = 
    [](int a, int b) { cout << "a: " << a << " b: " << b << endl; }
foo(func);

或内联:

foo(
    std::function<void(int, int)>(
        [](int a, int b) { cout << "a: " << a << "b: " << b << endl; }
));

std::function 有一个构造函数模板接受任何内容:

template<class F> function(F);

因此,编译器无法在重载解析期间知道要选择哪个 foo:两者都是 std::function和 std::function有一个构造函数,可以将 lambda 表达式作为参数。

当您直接传递 std::function 对象时,在重载决策期间会首选 std::function 复制构造函数,因此会选择它而不是构造函数模板。


未来的答案:如果保证捕获列表为空,也可以使用普通函数指针。在 C++0x 中,无捕获 lambda 可以隐式转换为函数指针。因此,您可以使用类似的方法

void foo(void (*t)(int, int)) { t(1, 2); }

void foo(void (*t)(int)) { t(1); }

并直接使用无捕获 lambda(或具有匹配类型的函数指针)调用 foo

请注意,此转换是语言标准草案中最近添加的内容(于今年 2 月添加),因此它还不太可能得到广泛支持。 Visual C++ 2010尚不支持;我不知道最新的g++。

The best way is to explicitly create a std::function object of the correct type then pass that object to the function:

std::function<void(int, int)> func = 
    [](int a, int b) { cout << "a: " << a << " b: " << b << endl; }
foo(func);

or inline:

foo(
    std::function<void(int, int)>(
        [](int a, int b) { cout << "a: " << a << "b: " << b << endl; }
));

std::function has a constructor template that accepts anything:

template<class F> function(F);

Because of this, there's no way for the compiler to know during overload resolution which foo to select: both std::function<void(int)> and std::function<void(int, int)> have a constructor that can take your lambda expression as an argument.

When you pass a std::function object directly, the std::function copy constructor is preferred during overload resolution, so it is selected instead of the constructor template.


Answer for the future: If the capture list is guaranteed to be empty, you can also use ordinary function pointers. In C++0x, a captureless lambda is implicitly convertible to a function pointer. So, you can use something like

void foo(void (*t)(int, int)) { t(1, 2); }

void foo(void (*t)(int)) { t(1); }

and call foo directly with the captureless lambda (or a function pointer with matching type).

Note that this conversion is a very recent addition to the draft language standard (it was added in February of this year), so it is not likely to be widely supported yet. Visual C++ 2010 doesn't support it yet; I don't know about the latest g++.

老子叫无熙 2024-10-07 17:09:48

我最近一直在考虑一个类似的问题,在寻找任何已知的解决方案时,我遇到了这篇文章,并且缺乏解决方案。

另一种解决方案是将函子抽象为模板参数,并使用 decltype 来解析其类型。因此,上面的示例将变为:

#include <iostream>
#include <functional>
using namespace std;

template<class F>
auto foo(F t) -> decltype(t(1,2))
{
    t(1, 2);
}

template<class F>
auto foo(F t) -> decltype(t(2)) 
{
    t(2);
}

int main()
{
     foo([](int a, int b){ cout << "a: " << a << " b: " << b << endl;});
}

这在 gcc 4.5 中按预期工作。

I've recently been thinking about a similar problem and when looking around for any known solutions I came across this post and lack of solutions for resolving

An alternative solution is to abstract over the functor as a template argument and use decltype to resolve its type. So, the above example would become:

#include <iostream>
#include <functional>
using namespace std;

template<class F>
auto foo(F t) -> decltype(t(1,2))
{
    t(1, 2);
}

template<class F>
auto foo(F t) -> decltype(t(2)) 
{
    t(2);
}

int main()
{
     foo([](int a, int b){ cout << "a: " << a << " b: " << b << endl;});
}

This works as expected with gcc 4.5.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文