为什么成员函数temporaries没有绑定到正确的类型?

Mat*_*man 6 c++ templates

假设我们有以下基类和派生类:

#include <string>
#include <iostream>

class Car {
public:
    void Drive() { std::cout << "Baby, can I drive your car?" << std::endl; }
};

class Porsche : public Car {
};
Run Code Online (Sandbox Code Playgroud)

..还有以下模板功能:

template <typename T, typename V>
void Function(void (T::*m1)(void), void (V::*m2)(void)) {
    std::cout << (m1 == m2) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

为什么使用GCC编译:

int main(int argc, char** argv) {
    void (Porsche::*ptr)(void) = &Porsche::Drive;
    Function(ptr, ptr);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

......但不是吗?

int main(int argc, char** argv) {
    void (Porsche::*ptr)(void) = &Porsche::Drive;
    Function(&Porsche::Drive, ptr);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*itb 7

int main(int argc, char** argv) {
    void (Porsche::*ptr)(void) = &Porsche::Drive;
    Function(&Porsche::Drive, ptr);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

ptr有类型void (Porsche::*)(),但&Porsche::Drive有类型void (Car::*)()(因为成员是在Car,而不是在Porsche).因此,调用的函数将这两个成员指针与这些类型进行比较,标准说

此外,可以比较指向成员的指针,或指向成员的指针和空指针常量.执行成员转换(4.11)和资格转换(4.4)的指针以使它们成为通用类型.如果一个操作数是空指针常量,则公共类型是另一个操作数的类型.否则,公共类型是指向成员类型的指针,类似于(4.4)与其中一个操作数的类型,具有cv-限定签名(4.4),它是操作数类型的cv限定签名的并集.

4.11描述了从隐式标准转换void (Base::*)()void (Derived::*)().因此,比较将找到共同类型void (Porsche::*)().对于类型的对象Porsche,两个成员指针都将引用相同的函数(即Car::Drive) - 因此比较将产生true.在科莫网编译如下这种解释和编译代码.