考虑这个模板功能:
template<typename ReturnT>
ReturnT foo(const std::function<ReturnT ()>& fun)
{
return fun();
}
为什么编译器不能从传递的调用签名中推导出ReturnT
?
bool bar() { /* ... */ }
foo<bool>(bar); // works
foo(bar); // error: no matching function call
答案 0 :(得分:15)
bool (*)()
类型的函数指针可以转换为std::function<bool()>
,但类型不同,因此需要进行转换。在编译器可以检查是否可以进行转换之前,需要将ReturnT
推导为bool
,但要做到这一点,它需要知道std::function<bool()>
是可能的转换,这不是可能直到它推断ReturnT
...看到问题?
另外,请考虑bool(*)()
也可以转换为std::function<void()>
或std::function<int()>
...应该推断出来?
考虑这种简化:
template<typename T>
struct function
{
template<typename U>
function(U) { }
};
template<typename T>
void foo(function<T>)
{ }
int main()
{
foo(1);
}
当编译器可以从function<int>
构建时,编译器如何知道您是想创建function<char>
还是function<void>
还是int
?
答案 1 :(得分:8)
std::function<bool()> bar;
foo(bar); // works just fine
C ++不能从函数bar
推导出返回类型,因为它必须知道类型才能找到所有带有函数指针的构造函数。
例如,谁说std::function<std::string()>
没有构建者使用bool (*)()
?
答案 2 :(得分:1)
函数bar
的类型为bool (*)()
左右,即:普通的C ++ 11之前的函数类型。我对C ++ 11没有那么自信,但我想编译器看不到bool (*)()
和const std::function<ReturnT()>&
之间的连接,即使第一个可以隐式转换为{{1}的第二个}}