Rudolfs Bundulis
Rudolfs Bundulis

Reputation: 11934

Error with templates on gcc/clang but not on MSVC

I am having issues with templates and portability. Given this MVCE:

#include <cstdio>

class C
{
public:
    void go()
    {
        printf("go\n");
    }
};

template<typename T>
class A
{
public:
    A(T* pInstance) : m_pInstance(pInstance)
    {
    }

protected:
    T* m_pInstance;
};

template<typename T>
class B : public A<T>
{
    using Base = A<T>;
public:
    B(T* pInstance) : A<T>(pInstance)
    {
    }

    void foo()
    {
        B::m_pInstance->go();
        C* a = nullptr;
        if (a == &B::m_pInstance)
        {
        }

    }
};

int main(int argc, char** argv)
{
    C c;
    B<C> b(&c);
    b.foo();
}

I get the error:

main.cpp:37:9: error: invalid operands to binary expression ('C *' and 'C *A<C>::*')
                if (a == &B::m_pInstance)
                    ~ ^  ~~~~~~~~~~~~~~~
main.cpp:48:4: note: in instantiation of member function 'B<C>::foo' requested here
        b.foo();
          ^
1 error generated.

But I am not sure why I get this? Ok I see how the types are different but why would the latter being a member cause this problem? Visual Studio (which of course does have a different template engine) handles the same fine.

Upvotes: 0

Views: 157

Answers (2)

Mihayl
Mihayl

Reputation: 3911

&B::m_pInstance is pointer to data member. You either have to change it to

if (a == this->B::m_pInstance)

or

if (a == B::m_pInstance)

If you want to compare them as pointer-to-members you have to change a's type like:

    T* (A<T>::*a) = nullptr;

or

    C* (A<C>::*a) = nullptr;

Upvotes: 2

Quentin
Quentin

Reputation: 63114

How MSVC handles that, I do not know -- but it sure is a bug.

&B::m_pInstance happens to be the syntax to form a pointer-to-member. You can disambiguate it to get the plain member access you expect with &(B::m_pInstance), but this then reveals another issue:

main.cpp:37:15: error: comparison of distinct pointer types ('C *' and 'C **')
        if (a == &(B::m_pInstance))
            ~ ^  ~~~~~~~~~~~~~~~~~

I guess what you really want is if(a == B::m_pInstance).

Upvotes: 0

Related Questions