user3279954
user3279954

Reputation: 586

Clang compiler error constructing object with operator T*

I am getting a strange compiler issue in clang (xcode). I just stripped down the code to just highlight the issue. When I construct the object I get an error in clang alone but works fine in msvc.

In the below code msvc correctly resolves the operator T* in the base and uses that to construct the derived in both the below cases. But clang wierdly allows only the second variant.

IDerivedT2 spDerived = spB; //Error

IDerivedT2 spDerived(spB); //Works

struct IBase    {      };

template <typename T>
struct CContainer
{
    CContainer() {}
    CContainer(T* p) {}

    CContainer& operator=(T* p)
    {
        return *this;
    }

    CContainer& operator=(CContainer& p)
    {
        return *this;
    }

    operator T*()
    {
        return nullptr;
    }
};

template <typename T>
struct CContainerDerived : public CContainer<T>
{
    CContainerDerived() : CContainer<T>() {}
    CContainerDerived(T* p) : CContainer<T>(p) {}
    CContainerDerived(IBase* p) { *this = p; }

    CContainerDerived& operator = (IBase* p)
    {
        return *this;
    }
};

struct IDerived : public IBase    {      };

typedef CContainer<IBase> IBaseT1;
typedef CContainerDerived<IDerived> IDerivedT2;

int main()
{
    IBaseT1 spB;
    IDerivedT2 spDerived = spB;  //Error

    //IDerivedT2 spDerived(spB);   //Works

    //IDerivedT2 spDerived;   //Works
    //spDerived = spB;

    std::cout << "Hello, world!\n";
}

http://rextester.com/VEVST22502 (clang)

http://rextester.com/ZOMDU93964 (msvc)

The version of clang compiler in my xcode is Apple LLVM version 7.3.0 (clang-703.0.29). The one in the rextester per commented code is 3.8. But behavior seems similar.

Any reason why this happens on the clang alone ?

Upvotes: 2

Views: 53

Answers (1)

MSalters
MSalters

Reputation: 180020

I was thrown of because MSVC does funky things with templates, in particular with name lookup, but this is actually easy.

It's CContainer& operator=(CContainer& p). You're missing a const there, it should be CContainer& operator=(CContainer const& p).

MSVC has another bug where it will bind temporaries to non-const references like p. Why does that temporary matter for you? Because copy-initialization IDerivedT2 spDerived = spB; involves a temporary IDerivedT2(spB) which doesn't exist with direct-initialization IDerivedT2 spDerived(spB).

Upvotes: 2

Related Questions