简体   繁体   English

为什么此typedef允许我在此模板中使用基类指向成员函数的指针?

[英]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. 模板期望objmethod具有相同的类型,但是它们并不完全相同。

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>::TypeDELEGATE出现在非推断上下文-编译器不能推断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.

相关问题 应该将基类的函数模板赋值给指向成员函数的指针 - Should function template of base class be assignable to pointer-to-member-function 为什么模板参数推导失败指针到成员函数? - Why is template argument deduction failing for pointer-to-member-function? 模板 function 不适用于采用 const ref 的指向成员函数的指针 - Template function does not work for pointer-to-member-function taking const ref 指针到成员功能错误 - Pointer-to-member-function error 覆盖指向成员函数的指针 - Override pointer-to-member-function 将没有复制构造函数的类的指向成员函数的指针传递到 Fortran - Pass pointer-to-member-function for class without copy constructor into Fortran 将一个指向成员的指针函数转换为同一个类的另一个指针 - Cast one pointer-to-member-function to another of same class 避免非类类型的指向成员函数 - avoid pointer-to-member-function for non-class type 标准对这个指向成员函数类型的模板参数有什么看法? 我的代码是错误的,还是 MSVS 16.6 有问题? - What does the standard say about this pointer-to-member-function type template parameter? Is my code wrong, or is MSVS 16.6 buggy? 返回指向成员函数的指针(没有typedef) - Returning pointer-to-member-function (without typedefs)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM