Overloading a function that takes a std::function with a different function signature results in compiler error

时间:2015-08-07 02:29:23

标签: templates c++11 overloading

I came across this compiler/language issue while working on a callback system. I'm using Visual Studio 2012. If I write:

// Works
template<typename T>
class C
{
};
C<void(int)>        a1;
C<void(int, int)>   a2;
void Good(C<void(int)>)         { }
void Good(C<void(int, int)>)    { }

void main()
{
    Good(a1);
    Good(a2);
}

it compiles cleanly and I verified in the debugger that the correct overloads are being called.

However, if I write:

void Foo(std::function<void(int)> fn)   { }
void Foo(std::function<void(int, int)> fn)  { } //<--- breaks compilation
void Bar(int a) { }

void main()
{
    Foo(Bar);
}

I get the following:

>c:\dev\newtech2\src\game.cpp(389): error C2668: 'Foo' : ambiguous call to overloaded function
>          c:\dev\newtech2\src\game.cpp(380): could be 'void Foo(std::function<_Fty>)'
>          with
>          [
>              _Fty=void (int,int)
>          ]
>          c:\dev\newtech2\src\game.cpp(379): or       'void Foo(std::function<_Fty>)'
>          with
>          [
>              _Fty=void (int)
>          ]
>          while trying to match the argument list '(overloaded-function)'

The compiler clearly knows that the two functions have different signatures due to the different template parameters, and it was able to distinguish the two in the previous example using my own template class. So is this a compiler/STL bug or some limitation in how std::function() works? Not a show-stopper but does limit one type of callback interface I wanted to provide.

1 个答案:

答案 0 :(得分:1)

在有效的示例中,参数a1a2的类型与两个Good重载的相应参数类型完全匹配。这不适用于第二个例子。选定的std::function构造函数是一个函数模板,与您提供的函数签名几乎没有关系。也就是说,在编译器的眼中,(尝试)将Bar转换为std::function<void(int)>并不比将其转换为std::function<void(int, int)>更好,尽管选择第二个最终将最终导致编译器错误(编译器无论如何都无法预见到这一点)。解决这种情况的一种方法是将参数Bar显式地转换为适当的std::function类型,或者自己制作一个方便的转换器包装器来自动执行此过程。