Templates std::function<;上的重载&燃气轮机;

Templates std::function<;上的重载&燃气轮机;,templates,lambda,c++11,overloading,Templates,Lambda,C++11,Overloading,给定以下代码:- #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); } i

给定以下代码:-

#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;
}
#包括
#包括
#包括
#包括
void func(标准::函数参数)
{
参数();
}
void func(标准::函数参数)
{
param(5);
}
int main(int argc,char*argv[])
{
func([]){std::cout _Fty=void(int)
1>          ]
1> CppTest.cpp(6):或“void func(std::tr1::function)”
1> 与
1>          [
1> _Fty=无效(无效)
1>          ]
1> 尝试匹配参数列表“(`匿名名称空间':)”
1> CppTest.cpp(19):错误C2668:“func”:对重载函数的调用不明确
1> CppTest.cpp(11):可能是“void func(std::tr1::function)”的
1> 与
1>          [
1> _Fty=void(int)
1>          ]
1> CppTest.cpp(6):或“void func(std::tr1::function)”
1> 与
1>          [
1> _Fty=无效(无效)
1>          ]
1> 尝试匹配参数列表“(`匿名名称空间':)”
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)>)
program2.cpp:在函数“int main(int,char**)”中:
program2.cpp:18:68:错误:重载“func(main(int,char**)::)”的调用不明确
程序2.cpp:6:10:注:候选项为:void func(std::function)
程序2.cpp:11:10:注:void func(std::function)
program2.cpp:19:79:错误:重载“func(main(int,char**)::)”的调用不明确
程序2.cpp:6:10:注:候选项为:void func(std::function)
程序2.cpp:11:10:注:void func(std::function)
因此,编译器似乎无法确定lambda[]()->void只能分配给std::函数,而lambda[](int)->void只能分配给std::函数。这是应该发生的还是编译器中的缺陷

这是应该发生的还是仅仅是编译器中的缺陷

这是应该发生的。
std::function
有一个构造函数模板,可以接受任何类型的参数。编译器只有在选择并实例化构造函数模板后才能知道它会出错,并且它必须能够选择函数的重载,然后才能这样做

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

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

(看起来你使用Visual C++ 2010,不支持这个转换。直到VisualStudio 2010发货之前,转换没有被添加到规范中,太晚了,不能添加它。)


为了更详细地解释这个问题,请考虑以下内容:

template <typename T>
struct function {

    template <typename U>
    function(U f) { }
};
参数类型,即我们将称之为
F
的一些无法表达的lambda类型名称,与这两个类型中的任何一个都不完全匹配,因此编译器开始查看它可以对
F
进行哪些转换,以尝试使其与这些候选函数之一匹配。在查找转换时,它会找到前面提到的构造函数temp晚了

编译器在这一点上看到的是,它可以调用任意一个函数,因为

  • 它可以使用其转换构造函数将
    F
    转换为
    std::function
    ,并
  • 它可以将
    F
    转换为
    std::function
    ,使用其具有
    U=F
    的转换构造函数

在您的示例中,很明显,其中只有一个转换会成功而没有错误,但在一般情况下,这是不正确的。编译器不能做任何进一步的事情。它必须报告歧义并失败。它不能选择一个,因为两个转换都一样好,并且重载都不比另一个好。

告诉我这是否正确。t他的代码片段也有同样的问题,原因相同(无法及时实例化Struct以确定func重载)?
模板Struct Struct{Struct(T var){};void func2(Struct obj){}void func2(Struct obj){}int main(){func2(2.5);}<代码> >这是一个有点不同的地方。这个错误是因为<代码> T <代码>是在一个非推导的上下文中。我会编辑一个解释到我的答案;这个注释不够大。在C++标准草案的许多领域中,委员会需要一些构造函数/函数模板被排除在过载解决方案中,如果有条件的话。不满足ns。这通常可以通过“SFINAE”来实现。(例如,请参见shared_ptr的模板构造函数)。我想知道为什么他们在这里没有对std::function做类似的事情。@sellibitze:我认为这可能会很困难,因为一个
std::function
可以存储这么多不同类型的类型。即使如此,在OP的情况下,仍然可能存在歧义,例如,如果您传递了一个
结构类型的对象{void operator()(){}void operator()(int){};
void func(void (*param)()) { }
void func(void (*param)(int)) { }
template <typename T>
struct function {

    template <typename U>
    function(U f) { }
};
void func(std::function<void(void)>)
void func(std::function<void(int)>)