I am just playing around to understand smart pointers and trying to make mine but I come across a situation that I do not fully understand. Here is the code:
#include <iostream>
template <class T>
class Holder
{
private:
T * obj;
public:
Holder(T * tt) : obj(tt)
{
std::cout << "ctor : " << tt->dummy << std::endl;
}
T * operator -> ()
{
return obj;
}
operator bool()
{
return obj;
}
T * const get() const
{
return obj;
}
void reset() {swap(0);}
void swap(T * other)
{
obj = other;
}
Holder & operator = (const Holder& holder)
{
obj = holder.get();
return *this;
}
Holder(const Holder & holder) : obj(holder.get()) {}
};
class A
{
public:
int dummy;
A(int a) : dummy(a) {}
};
int main ()
{
A * a = new A(1);
Holder<A> holder(a);
A * b = new A(2);
holder = b;
std::cout << holder->dummy << std::endl;
return 0;
}
The code compiles and on the line of holder = b;
the constructor of Holder
class is called. I thought compiler would give an error. It is not the assingment operator but why is it calling constructor?
holder = b
attempts to assign from b
to Holder
. b
is of type A*
, and holder
is of type Holder<A>
.
The Holder
template defines assignment from another instance of the same Holder
type, so the compiler looks for a conversion from A*
to Holder<A>
. It finds the constructor, and uses that.
Constructors which may take exactly one argument may be used for implicit conversions, unless you tag them with the explicit
keyword.
Both the constructor and assignment operator are called. You can check this by printing something in operator =
.
This happens because operator =
is defined to take a const Holder &
, but b
is of type A *
. So first the Holder(T *)
constructor is called to create a temporary object, then this object is assigned to holder
through operator =
.
If you define an operator =(const T *)
, only the assignment operator will be called.
I do not see a version of the assignment operator that takes a right hand side of A*
A* a = new A(1);
Holder<A> holder(a);
A* b = new A(2);
// assigning object of type A* to Holder<A>
holder = b;
// No appropriate assignment operator provide.
// But a constructor is available to convert RHS parameter to correct type.
// So compiler generates the following code:
holder = Holder<A>(b);
// There is an appropriate assignment operator for this.
// So it compiles.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With