2013-07-21 65 views
1
#include <functional> 

void foo(std::function<void()> f) { f(); } 
void foo(void (*f)()) { f(); } 

int main() 
{ 
    foo([](){}); 
} 

VS编译,gcc和clang抱怨模糊超载。谁是对的? lambda应该是类的类型,所以它和函数指针之间不应有任何转换。因此,VS似乎是正确的,而不是一切困难。但也许我错过了一些东西。函数指针和std :: function模糊过载

除了将lambda投射到任一类型之外,是否有简单的方法来消除调用的歧义?

+2

不捕获任何东西(空'''')*的Lambda可以*隐式转换为相同签名的函数指针。 VS(至少你使用的版本)还没有实现。 – JohannesD

+0

@JohannesD OK发现这在5.1.2/6中提到。请让你的评论一个答案,以便我可以接受它。 –

+1

你可以尝试用'f(+ [](){});'来消除歧义。希望这可以帮助。 –

回答

3

未捕获的lambdas具有隐式转换为具有相同签名的函数指针。

的闭合类型没有λ-捕获的λ-表达具有 公共非虚拟非显式const的转换函数的指针 起作用具有:这在章节5.1.2第6段指定与关闭 类型的函数调用操作符相同的参数和返回类型。这个转换函数 函数返回的值应该是一个函数的地址,该函数在被调用时具有与调用闭包类型的函数调用操作符相同的效果 。

4

lambda创建一个可以调用的匿名和未指定的对象,它既不是函数指针也不是对象,但可用作函数指针和对象,为您提供不明确的过载错误。我会说VS是错的。另外,由于可以使用函数指针创建一个对象,所以如果您已经有一个函数采用std::function参数,那么不需要使用带有函数指针的重载。

+1

该标准说:* lambda表达式的类型(这也是闭合对象的类型)是一个独特的,未命名的不连贯 _class type_ *。函数指针重载更为有效,因为'std :: function'涉及各种开销(在我的特殊情况下不重要,但原则上我不应该为此付出代价)。 –

+0

@ n.m - 不管它是否是类的类型,在这里都没有关系 - 类过滤器类类型和内置类型之间的转换在重载解析算法中是相同的。仅仅为了lambda而添加一个特例就是一个不必要的复杂性。 – JohannesD

+0

@JohannesD - *为什么*在这个特定的类类型和函数指针类型之间有转换?标准是否明确提到了这种转换? –