Hmm. Thought I was getting quite good at this c++ lark, but there’s always something to learn…
I had changed the copy constructor to take a templated parameter, so that it can be used to copy from arrays of compatible polymorphic types. I assumed that this method would also work perfectly well as the normal copy constructor, but it seems not. I don’t know if it’s because of a compiler idiosyncrasy, or perhaps an obscure footnote in the c++ standard, but for some reason the compiler is refusing to use my templated version in cases where it could use a standard copy constructor.
Anyway, I’ve added a normal copy constructor to the class now, so it should all work!
The official reason is that a template copy constructor can not exist.
What you’ve made is a template constructor that “behave” like a copy constructor.
The standard state that if a copy constructor doesn’t exists, the compiler must provide an implicit one, bypassing any template lookup at the time.
It seems a bit illogical to me… When the compiler needs a copy constructor, I’d have thought that it would just look for a function that fits the requirement, just like it does when you make any other function call. Can’t really see why there’d need to be a special case for a copy constructor, but I’m sure there’s a very obscure and convoluted reason why it has to be done that way!
The reason is in the implicit part. Copy constructor and assignment operator are special case in C++, as they are the only methods that a compiler can write itself.
Usually, the method resolution logic is:
If there is a perfect fit, use it
If a default type conversion can do, to use the perfect fit, use it.
If there is a template version that could match better than any other template one, instantiate it and use it.
For copy constructor, I guess the implicit part comes in between 1 and 2, stating “if 1 or 2 doesn’t do, write my own implicit code and use it”.
If you think about it more deeply, it make sense.
This code:
template<T>
class Any
{
template <typename U>
Any(U & u); // Conversion constructor
};
would be at the same time an “accept-all-types” and a copy constructor (when U = const Any), yet the developper probably doesn’t want this (if he either thought about this).
I guess in c++11 it could be done more neatly by using the “X (const X&) = delete” notation, or even by writing a default constructor that calls the templated constructor. It’s just a bit annoying in c++03 to have to write basically the same function twice.