Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't member function temporaries bind to the right type?

Tags:

c++

templates

Suppose that we have the following base and derived classes:

#include <string>
#include <iostream>

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

class Porsche : public Car {
};

..and also the following template function:

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

Why does this compile using GCC:

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

...but not this?

int main(int argc, char** argv) {
    void (Porsche::*ptr)(void) = &Porsche::Drive;
    Function(&Porsche::Drive, ptr);
    return 0;
}
like image 609
Matt Fichman Avatar asked Sep 17 '09 18:09

Matt Fichman


1 Answers

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

ptr has type void (Porsche::*)(), but &Porsche::Drive has type void (Car::*)() (because the member is found in Car, not in Porsche). Thus the function called compares these two member pointers with those types, and the standard says

In addition, pointers to members can be compared, or a pointer to member and a null pointer constant. Pointer to member conversions (4.11) and qualification conversions (4.4) are performed to bring them to a common type. If one operand is a null pointer constant, the common type is the type of the other operand. Otherwise, the common type is a pointer to member type similar (4.4) to the type of one of the operands, with a cv-qualification signature (4.4) that is the union of the cv-qualification signatures of the operand types.

4.11 describes an implicit Standard conversion from void (Base::*)() to void (Derived::*)(). Thus, the comparison would find the common type void (Porsche::*)(). For an object of type Porsche, both member pointers would refer to the same function (which is Car::Drive) - so the comparison would yield true. The comeau web compiler follows this interpretation and compiles your code.

like image 69
Johannes Schaub - litb Avatar answered Oct 11 '22 22:10

Johannes Schaub - litb