[英]C++ derived class overloaded function (with std::function argument) not visible
Let me illustrate my question with following example. 让我用下面的例子说明我的问题。 Suppose we have a base class that defines method Exec that takes one argument of any type (template).
假设我们有一个基类,它定义了一个方法Exec ,它接受任何类型(模板)的一个参数。 The method Exec calls then method Call that has been overloaded to take as an argument an std::function object with different parameters.
方法Exec调用then方法调用已经重载的方法,将带有不同参数的std :: function对象作为参数。
Now suppose we have a derived class that inherits after Base and overloads Exec so it takes as an argument yet another std::function object (with different argument set). 现在假设我们有一个派生类,它在Base之后继承并重载Exec,因此它将另一个std :: function对象(具有不同的参数集)作为参数。
Something like: 就像是:
struct Base
{
template<typename Func>
static void Exec( Func func )
{
Call( func );
}
static void Call( std::function<void(void)> func )
{
func();
}
/*other definitions of Call for other std::functions*/
};
struct Derived : public Base
{
using Base::Exec;
static void Exec( std::function<void(int)> func )
{
func( 10 );
}
};
Now suppose we want to call: 现在假设我们要打电话:
Derived::Exec( []( int i ){std::cout << i << std::endl;} );
this will give following compilation error (I tried with g++ 4.8.5 and 8.1.1): 这将产生以下编译错误(我尝试使用g ++ 4.8.5和8.1.1):
error: no matching function for call to 'Base::Call(main(int, char**)::<lambda(int)>&)'
My question is: why does the compiler not see the definition of Exec
in Derived class ( void Derived::Exec( std::function<void(int)> func )
)? 我的问题是:为什么编译器在Derived类中看不到
Exec
的定义( void Derived::Exec( std::function<void(int)> func )
)? I would expect that during overload resolution the Derived::Exec
will be chosen as it is most appropriate for the given argument: 我希望在重载解析期间选择
Derived::Exec
因为它最适合给定的参数:
[]( int i ){std::cout << i << std::endl;}
What am I missing? 我错过了什么?
Lambda expressions produce closures that have anonymous and unique types. Lambda表达式生成具有匿名和唯一类型的闭包 。 These types are completely unrelated from
std::function
. 这些类型与
std::function
完全无关。
Your template
is a better match as it can deduce the exact type of the closure . 您的
template
是一个更好的匹配,因为它可以推断出闭包的确切类型。 Invoking the non- template
overload would require an std::function
instance to be created from the closure (not an exact match). 调用非
template
重载将需要从闭包创建std::function
实例(不是精确匹配)。
The lambda []( int i ){std::cout << i << std::endl;}
is convertible to std::function<void(int)>
not to std::function<void(void)>
. lambda
[]( int i ){std::cout << i << std::endl;}
可转换为std::function<void(int)>
而不是std::function<void(void)>
。
Even when the template function in Base is being selected because of perfect match, inside of it you're passing func
to Base::Call
that accept something convertible to std::function<void(void)>
, and the lambda is not. 即使在Base中的模板函数由于完美匹配而被选中时,你也可以将
func
传递给Base::Call
,它接受可转换为std::function<void(void)>
,而lambda则不然。 Derived::Call
is never selected because of static dispatch, that's the reason of the error. Derived::Call
由于静态调度而从未选择Derived::Call
,这就是错误的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.