I have a subset of a pointer class that look like:
template <typename T>
struct Pointer
{
Pointer();
Pointer(T *const x);
Pointer(const Pointer &x);
template <typename t>
Pointer(const Pointer<t> &x);
operator T *() const;
};
The goal of the last constructor is to allow to pass a Pointer
of a subclass, or basically any type that is implicitly convertable to T *
. This actual rule is only enforced by the definition of the constructor and the compiler can't actually figure it out by the declaration alone. If I drop it, and try to pass a Pointer<Sub>
to a constructor of Pointer<Base>
, I get a compile error, despite of the possible path through operator T *()
.
While it solves the above problem, it creates another one. If I have an overloaded function whose one overload takes a Pointer<UnrelatedClass>
and the other takes Pointer<BaseClass>
, and I try to invoke it with a Pointer<SubClass>
, I get an ambiguity between the two overloads, with the intention, ofcourse, that the latter overload will be called.
Any suggestions? (Hopefully I was clear enough)
The cure for your problem is called SFINAE (substitution failure is not an error)
If U* is convertible to T* the
enable_if
will have a typedef membertype
defaulting to void. Then, everything is fine. If U* is not convertible to T* this typedef member is missing, substitution fails and the constructor template is ignored.This solves your conversion and ambiguity problems.
In response to the comment:
is_convertible
looks something like this: