[英]Why does this typedef allow me to use a base class pointer-to-member-function in this template?
If I attempt to compile the following code in MSVC: 如果我尝试在MSVC中编译以下代码:
template <typename DELEGATE>
void newButton(DELEGATE *obj, int (DELEGATE::*method)(int))
{
std::function<int(int)> callback = std::bind(
method, obj, std::placeholders::_1);
// ...
}
class Base
{
public:
virtual int test(int f) { return f * f; }
};
class Derived : public Base
{
};
int main()
{
Derived d;
newButton(&d, &Base::test);
}
I get a compiler error: 我收到编译器错误:
'void newButton(DELEGATE *,int (__thiscall DELEGATE::* )(int))' :
template parameter 'DELEGATE' is ambiguous
could be 'Base'
or 'Derived'
This is reasonable. 这是合理的。 The template expects an identical type for
obj
and method
, but they are not exactly the same. 模板期望
obj
和method
具有相同的类型,但是它们并不完全相同。
BUT, if I replace the pointer-to-member-function declaration with this template struct typedef, it compiles! 但是,如果我用此模板struct typedef替换了指向成员函数的指针声明,它将编译!
template <typename DELEGATE>
struct ButtonAction
{
typedef int (DELEGATE::*Type)(int);
};
template <typename DELEGATE>
void newButton(DELEGATE *obj, typename ButtonAction<DELEGATE>::Type method)
{
std::function<int(int)> callback = std::bind(
method, obj, std::placeholders::_1);
// ...
}
// rest same as before
Why? 为什么? I would have expected the typedef to get resolved down to the exact same pointer-to-member-function type, and cause the same template error.
我本来希望typedef解析为完全相同的指针到成员函数类型,并导致相同的模板错误。
The reason is that in ButtonAction<DELEGATE>::Type
, DELEGATE
appears in a non-deduced context - the compiler cannot deduce DELEGATE
from this, so it does not try. 其原因是,在
ButtonAction<DELEGATE>::Type
, DELEGATE
出现在非推断上下文-编译器不能推断DELEGATE
从此,所以它不会尝试。 Therefore, the deduction is performed from the first argument only, and so it's unambiguous. 因此,推论仅从第一个参数执行,因此它是明确的。
As to why DELEGATE
cannot be deduced in this context - try to imagine what the process would need to be: inspect ButtonAction<T>
for every possible type T
and compare its nested typedef Type
against the argument type. 至于为什么
DELEGATE
不能在此背景下推断-试着想象一下过程将需要:检查ButtonAction<T>
每一个可能的类型T
,并比较其嵌套的typedef Type
对参数的类型。 And note that there are infinitely many possible types. 并且请注意,存在无限多种可能的类型。
A rule of thumb is: everything to the left of ::
is a non-deduced context. 经验法则是:一切的左边
::
是一种非推断上下文。
在第二个示例中, method
参数不参与类型推导,因此将DELEGATE
推导为Derived
,并将&Base::test
隐式转换为(Derived::*)(int)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.