gpt4 book ai didi

templates - std::function<...> 上的重载

转载 作者:行者123 更新时间:2023-12-02 21:44:19 25 4
gpt4 key购买 nike

给出以下代码:-

#include <algorithm>
#include <iostream>
#include <functional>
#include <string>

void func(std::function<void(void)> param)
{
param();
}

void func(std::function<void(int)> param)
{
param(5);
}

int main(int argc, char* argv[])
{
func([] () { std::cout << "void(void)" << std::endl; });
func([] (int i) { std::cout << "void(int): " << i << std::endl; });

std::string line;
std::getline(std::cin, line);
return 0;
}

VS2010 编译错误:-

CppTest.cpp(18): error C2668: 'func' : ambiguous call to overloaded function
1> CppTest.cpp(11): could be 'void func(std::tr1::function<_Fty>)'
1> with
1> [
1> _Fty=void (int)
1> ]
1> CppTest.cpp(6): or 'void func(std::tr1::function<_Fty>)'
1> with
1> [
1> _Fty=void (void)
1> ]
1> while trying to match the argument list '(`anonymous-namespace'::<lambda0>)'
1>CppTest.cpp(19): error C2668: 'func' : ambiguous call to overloaded function
1> CppTest.cpp(11): could be 'void func(std::tr1::function<_Fty>)'
1> with
1> [
1> _Fty=void (int)
1> ]
1> CppTest.cpp(6): or 'void func(std::tr1::function<_Fty>)'
1> with
1> [
1> _Fty=void (void)
1> ]
1> while trying to match the argument list '(`anonymous-namespace'::<lambda1>)'

g++-4.5 编译错误

program2.cpp: In function ‘int main(int, char**)’:
program2.cpp:18:68: error: call of overloaded ‘func(main(int, char**)::<lambda()>)’ is ambiguous
program2.cpp:6:10: note: candidates are: void func(std::function<void()>)
program2.cpp:11:10: note: void func(std::function<void(int)>)
program2.cpp:19:79: error: call of overloaded ‘func(main(int, char**)::<lambda(int)>)’ is ambiguous
program2.cpp:6:10: note: candidates are: void func(std::function<void()>)
program2.cpp:11:10: note: void func(std::function<void(int)>)

所以编译器似乎无法弄清楚 lambda [] () -> void 只能分配给 std::function ,而 lambda [] (int) -> void 只能分配给 std::function 。这是应该发生的还是只是编译器的缺陷?

最佳答案

Is this supposed to happen or just a deficiency in the compilers?

这应该会发生。 std::function有一个可以接受任何类型参数的构造函数模板。编译器直到选择并实例化构造函数模板之后才能知道它将遇到错误,并且它必须能够选择函数的重载才能执行此操作。

最直接的修复方法是使用强制转换或显式构造 std::function正确类型的对象:

func(std::function<void()>([](){}));
func(std::function<void(int)>([](int){}));

如果您的编译器支持无捕获 lambda 到函数指针转换,并且您的 lambda 不捕获任何内容,则可以使用原始函数指针:

void func(void (*param)()) { }
void func(void (*param)(int)) { }

(看起来您使用的是 Visual C++ 2010,它不支持此转换。直到 Visual Studio 2010 发布之前,该转换才添加到规范中,来不及添加。)

<小时/>

要更详细地解释该问题,请考虑以下内容:

template <typename T>
struct function {

template <typename U>
function(U f) { }
};

这基本上就是 std::function 的内容有问题的构造函数看起来像: 您可以使用任何参数调用它,即使该参数没有意义并且会在其他地方导致错误。例如,function<int()> f(42);将使用 U = int 调用此构造函数模板.

在您的具体示例中,编译器在重载决策期间找到两个候选函数:

void func(std::function<void(void)>)
void func(std::function<void(int)>)

参数类型,一些无法说出的 lambda 类型名称,我们将其称为 F ,与其中任何一个都不完全匹配,因此编译器开始查看它可以对 F 进行哪些转换尝试使其与这些候选函数之一匹配。当寻找转换时,它会找到前面提到的构造函数模板。

编译器此时看到的只是它可以调用任一函数,因为

  • 它可以转换Fstd::function<void(void)>使用其转换构造函数 U = F
  • 它可以转换Fstd::function<void(int)>使用其转换构造函数 U = F .

在您的示例中,很明显只有其中之一会成功且不会出现错误,但在一般情况下情况并非如此。编译器不能做任何进一步的事情。它必须报告歧义并失败。它无法选择其中一个,因为两种转换都同样好,而且两种重载都不比另一种更好。

关于templates - std::function<...> 上的重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4731947/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com