Reputation: 586
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
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