传递函数对象时函数重载歧义

时间:2016-04-21 20:36:08

标签: c++ overloading

我以一种令我挠头的方式打破了一些代码。以下演示了该问题( http://ideone.com/TsRPcx 的完整代码):

#include <functional>

typedef std::function<bool()> BoolCallback;
typedef std::function<void()> VoidCallback;

// Support two types of callback
void scan( BoolCallback func ) {}
void scan( VoidCallback func ) {}

int main( int argc, char* argv[] )
{
    scan( [] {} );                          // Original, unambiguous.
    scan( [] { return true; } );            // New, broken call. Ambiguous.
}

使用gcc 5.1,第一个调用编译好,但第二个调用call of overloaded ‘scan(main(int, char**)::<lambda()>)’ is ambiguous。所以第一个问题是,这些调用中的一个如何可以正常,另一个是不明确的?

认为这可能与我正在使用的lambda表达式有关,我尝试了一些其他方法(扰乱警报:它们都产生相同的结果):

    scan( []() -> void {} );                // Unambiguous
    scan( []() -> bool { return true; } );  // Ambiguous

    auto vcb = []() -> void {};
    auto bcb = []() -> bool { return true; };
    scan( vcb );                            // Unambiguous
    scan( bcb );                            // Ambiguous

    extern void voidCallback();
    extern bool boolCallback();
    scan( voidCallback );                   // Unambiguous
    scan( boolCallback );                   // Ambiguous, so it's not the lambdas

    scan( (VoidCallback)vcb );              // Unambiguous
    scan( (BoolCallback)bcb );              // Eureka!

显式强制转换可以解决歧义,将上面的bcb明确声明为BoolCallback而不是auto(未显示)。

最后,我尝试更改回调类型:

typedef void (*VoidCallback)();
typedef bool (*BoolCallback)();

嗯...这适用于上述所有情况。它不是解决方案,因为这是需要std::function提供的通用性的库代码,但它很有趣。

有人可以解释为什么这对于没有返回任何值的std::function对象或者在任何情况下对于原始函数指针来说都是明确的,但是否则是不明确的?

0 个答案:

没有答案