Arn*_*ion 13 lambda templates overloading c++11
鉴于以下代码: -
#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;
}
Run Code Online (Sandbox Code Playgroud)
从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>)'
Run Code Online (Sandbox Code Playgroud)
从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)>)
Run Code Online (Sandbox Code Playgroud)
所以似乎编译器无法弄清楚lambda []() - > void只能分配给std :: function <void(void)>,而lambda [](int) - > void只能被分配给std :: function <void(int)>.这是应该发生还是仅仅是编译器中的缺陷?
Jam*_*lis 13
这是应该发生还是仅仅是编译器中的缺陷?
这应该发生. std::function有一个构造函数模板,可以采用任何类型的参数.编译器无法知道,直到选择构造函数模板并将其实例化后才会遇到错误,并且它必须能够在执行此操作之前选择函数的重载.
最直接的解决方法是使用强制转换或显式构造std::function正确类型的对象:
func(std::function<void()>([](){}));
func(std::function<void(int)>([](int){}));
Run Code Online (Sandbox Code Playgroud)
如果你有一个支持captureless-lambda-to-function-pointer转换的编译器,而你的lambda没有捕获任何东西,你可以使用原始函数指针:
void func(void (*param)()) { }
void func(void (*param)(int)) { }
Run Code Online (Sandbox Code Playgroud)
(看起来你使用的是Visual C++ 2010,它不支持这种转换.直到Visual Studio 2010发布之前,转换才被添加到规范中,为时已晚,无法添加.)
要更详细地解释问题,请考虑以下事项:
template <typename T>
struct function {
template <typename U>
function(U f) { }
};
Run Code Online (Sandbox Code Playgroud)
这基本上是所讨论的std::function构造函数的样子:你可以用任何参数调用它,即使参数没有意义并且会在其他地方引起错误.例如,function<int()> f(42);将调用此构造函数模板U = int.
在您的特定示例中,编译器在重载解析期间找到两个候选函数:
void func(std::function<void(void)>)
void func(std::function<void(int)>)
Run Code Online (Sandbox Code Playgroud)
参数类型,我们将引用的一些不可言说的lambda类型名称,F与这两者中的任何一个都不完全匹配,因此编译器开始查看它可以做什么转换F以尝试使其与这些候选函数之一匹配.在查找转换时,它会找到上述构造函数模板.
此时所有编译器都看到它可以调用任一函数,因为
F为std::function<void(void)>使用U = F和转换构造函数F为std::function<void(int)>使用其转换构造函数U = F.在您的示例中,很明显只有其中一个会成功而没有错误,但在一般情况下并非如此.编译器无法继续做任何事情.它必须报告歧义并失败.它不能选择一个,因为两个转换同样好,并且过载都不比另一个好.
| 归档时间: |
|
| 查看次数: |
2605 次 |
| 最近记录: |