Error while implementing smart pointer class - c++

I am stuck at a single error. Here is my code:
template<class t>
class smart_ptr{
t *ptr;
public:
smart_ptr(t *p):ptr(p){cout<<"smart pointer copy constructor is called"<<endl;}
~smart_ptr(){cout<<"smart pointer destructor is called"<<endl;delete(ptr);}
t& operator *(){cout<<"returning the * of pointer"<<endl;return(*ptr);}
t* operator ->(){cout<<"returning the -> of pointer"<<endl;return(ptr);}
t* operator=(const t &lhs){ptr=lhs;cout<<"assignement operator called"<<endl;}
};
class xxx{
int x;
public:
xxx(int y=0):x(y){cout<<"xxx constructor called"<<endl;}
~xxx(){cout<<"xxx destructor is called"<<endl;}
void show(){cout<<"the value of x="<<x<<endl;}
};
int main(int argc, char *argv[])
{
xxx *x1=new xxx(50);
smart_ptr<xxx *> p1(x1);
return 0;
}
While compilation I am getting below error
smart_pointer_impl.cpp: In function ‘int main(int, char**)’:
smart_pointer_impl.cpp:27: error: no matching function for call to ‘smart_ptr::smart_ptr(xxx*&)’
smart_pointer_impl.cpp:7: note: candidates are: smart_ptr::smart_ptr(t*) [with t = xxx*]
smart_pointer_impl.cpp:4: note: smart_ptr::smart_ptr(const smart_ptr&)
Any help for a solution is most welcome.

Presumably smart_ptr is template<class t> and then in the main there was intended to be smart_ptr<xxx> instead of smart_ptr<xxx*>?

You need to change ::
smart_ptr<xxx *> p1(x1); to smart_ptr<xxx> p1(x1);
it will work.

You have, I hope, forgotten the first line of your code, that being
template<class t>
and this line:
smart_ptr<xxx *> p1(x1);
should be:
smart_ptr<xxx> p1(x1);

You've not declared your class smart_ptr as a template
template <TYPE>
class smart_ptr{
TYPE *ptr;
public:
smart_ptr(TYPE *p):ptr(p){cout<<"smart pointer copy constructor is called"<<endl;}
~smart_ptr(){cout<<"smart pointer destructor is called"<<endl;delete(ptr);}
TYPE& operator *(){cout<<"returning the * of pointer"<<endl;return(*ptr);}
TYPE* operator ->(){cout<<"returning the -> of pointer"<<endl;return(ptr);}
TYPE* operator=(const TYPE &lhs){ptr=lhs;cout<<"assignement operator called"<<endl;}
};
Also, you're declaring your pointer as of type 'pointer to xxx' but your template class is of a pointer to the type. Try:
smart_ptr<xxx> p1(x1);

Related

decltype of pointer to class accessing its () operator

I have following class
template<class T> class CT
{
T& operator()(int i,int j) const noexcept
{ return indx[i*N+j]; }
private:
T *indx;
int N;
};
Now some where in my application I have something as the following
CT<double> arr, (...);
(...)
decltype(arr) *alias;
if(usearr)alias = &arr;
(...)
alias(0,0) = 3.0; // Compiler ERROR!
The compiler complains that the object type I am accessing through decltype is not a function or function pointer.
The problem can be solved if I remove the pointer in declaring alias and replaces the line to an assignment overload
decltype(arr) alias;
if(usearr)alias = arr;
What is wrong with the former approach ?
decltype(arr) yields the type of arr, i.e. CT<double>, then decltype(arr) * yields the type CT<double> *, which is a pointer to CT<double> and you can't call operator() on it directly.
You can dereference it then call operator() like (*alias)(0,0).

Pointer by reference on templates and normal functions

Here is my code :
#include <iostream>
template<typename B>
class test{
public:
B* t;
test(const B& init){
}
};
void funct(const int*& test){
}
int main(int argc, char** argv) {
test<int*> t(new int(2)); // works fine
funct(new int(2)); //error
return 0;
}
I am trying to emulate what's happening on my templated class, but somehow i get errors. I believe that const B& init with B as int* will be const int*& init. Adding const allowed it to accept temporary "new"s. I made a non-templated function to test it and it has this header, void funct(const int*& test). It is just the same as above but how come it wont take new int(2) ?
const int*& means "reference to pointer to const int. You need the const to apply to the pointer, not to the int:
void funct(int* const& test){}
This is what the template version does. T is a pointer to int, so T& is really a reference to pointer to int. The template does not perform a textual substitution of T for int*. It substitutes the type. You'd get the same if you used typedef int* X and const X&.

How does one use inheritance when we have a template class have template pointer

How does one use inheritance when we have a template class have template pointer
We know that base class pointer can easily point to a derived class object . I created another template class and passed base and derived in it . However even with an overloaded = operator i cant make then equal which is my need .
Please take a look at my sample code as it explains clearly the situation.
#include <iostream>
using namespace std;
class base1
{
public:
int a;
virtual int reset(){
a=0;
return a;
}
};
class derived1: public base1
{
public:
int b;
int reset(){
b=0;
return b;
}
};
template <class T>
class templateClass{
public:
T *P;
T& operator = (templateClass &b )
{
this.p = reinterpret_cast<T>(b.p);
return *this;
}
void resetMyself(){
P->reset();
}
};
int main() {
// your code goes here
templateClass<base1> *p = new templateClass<base1> () ;
templateClass<derived1> *q = new templateClass<derived1>() ;
p=q;
p->resetMyself();
return 0;
}
When i compile my code i get
prog.cpp: In function ‘int main()’:
prog.cpp:44:3: error: cannot convert ‘templateClass<derived1>*’ to ‘templateClass<base1>*’ in assignment
p=q;
^
templateClass<derived1> and templateClass<base1> are as different as int and double. You can't assign a pointer to one to a pointer to the other.
You can, however, make templateClass<derived1> assignable to templateClass<base1> with a custom templated assignment operator:
template <class T>
class templateClass{
public:
T *P;
template <class U>
templateClass& operator = (const templateClass<U> &b )
{
P = b.P;
return *this;
}
void resetMyself(){
P->reset();
}
};
Then you can do something like (demo):
templateClass<base1> p;
templateClass<derived1> q;
p = q;
Note that your original assignment operator's signature is incorrect. Also, reinterpret_cast is a terrible idea for this. To perform a pointer-to-base to pointer-to-derived conversion, use static_cast. The above version uses no cast and so allows implicit conversions only (i.e., from derived to base but not the other way around).

C++ template member function having pointer reference template parameter

class BI {
public:
virtual void fun() = 0;
virtual ~BI() {}
};
class B : public BI {
public:
void fun() {}
};
template <typename T>
class A {
T* obj;
public:
void funT(const T*&) /* adding reference is creating error */;
};
template <typename T>
void A<T>::funT(const T*& obj) {
}
int main() {
A<B> obj;
obj.funT(new B());
}
when compiling the above code with g++ compiler, I am getting the error: no matching function for call to A::funT(B)*. But when I remove the reference '&' operator from the funT() declaration as void funT(const T* obj), then it compiles and works fine. Why the reference operator is not allowed here?
You're asking for a reference to a pointer, you can't get references (unless they're C++11 rvalue references) to temporary values.
Make sure you have a lvalue passed as parameter to have the reference working.
e.g.
#include <iostream>
using namespace std;
class BI {
public:
virtual void fun() = 0;
virtual ~BI() {}
};
class B : public BI {
public:
void fun() {}
};
template <typename T>
class A {
T* obj;
public:
void funT(const T*&);
};
template <typename T>
void A<T>::funT(const T*& obj) {
}
int main() {
A<B> obj;
const B* ptr = new B(); // <-- This is an lvalue
obj.funT(ptr);
delete ptr; // Also clean it up after you used it
}
http://ideone.com/T4QJzi
Here is a more simple program which exhibits the same problem:
void fun(const int*&) {}
int main() {
int x;
fun(&x);
}
It yields the following error:
invalid initialization of non-const reference of type ‘const int*&’
from an rvalue of type ‘int*’
That makes sense. fun takes an argument of type "reference to non-const pointer to const int", and we tried to pass it a temporary of type "pointer to int". References to non-const types don't bind to temporaries, because temporaries are usually immutable. In this case, if we were allowed to pass &x as the argument to fun, then fun would be able to modify the address of x, which doesn't make any sense.
As you noticed, removing the & makes the code well formed:
void fun(const int*) {}
Now we are simply passing a pointer to int where a value of type pointer to const int is expected, which is a simple implicit conversion.
Alternatively, you might have intended for fun to take an argument of type "reference to const pointer to int":
void fun(int* const&) {}
Or a reference to const pointer to const int:
void fun(const int* const&) {}
But a reference to a const pointer is kind of silly, as a simple pointer would be just as good.
Finally, you could keep your original declaration of fun, and just avoid trying to pass a temporary as its argument.
The error msg is clear. Parameter type is of reference to pointer to T, but you are sending pointer to T. Temporaries cannot be passed as reference in this case. You can write:
int main() {
A<B> obj;
const B* b=new B(); //create a lvalue
obj.funT(b);
delete b; // make sure to release memory.
}

smart pointer implementation error in code

Here is my code below:
template<class t>
class smart_ptr{
t *ptr;
public:
smart_ptr(t *p):ptr(p){cout<<"smart pointer copy constructor is called"<<endl;}
smart_ptr(const smart_ptr &sm){cout<<"copy constructor is called"
<<endl;ptr=sm->ptr;}
~smart_ptr(){cout<<"smart pointer destructor is called"<<endl;delete(ptr);}
t& operator *(){cout<<"returning the * of pointer"<<endl;return(*ptr);}
t* operator ->(){cout<<"returning the -> of pointer"<<endl;return(ptr);}
t& operator=(const t &lhs){ptr=lhs->ptr;cout<<"assignement operator called"
<<endl;return *this;}
};
class xxx{
int x;
public:
xxx(int y=0):x(y){cout<<"xxx constructor called"<<endl;}
~xxx(){cout<<"xxx destructor is called"<<endl;}
void show(){cout<<"the value of x="<<x<<endl;}
};
int main(int argc, char *argv[])
{
xxx *x1=new xxx(50);
smart_ptr<xxx> p2(new xxx(60));
smart_ptr<xxx> p1(x1);
p1->show();
smart_ptr<xxx> p3(p2); //calling copy construcotr is giving error
p3=p1; //calling assignment operator is giving error
p2->smart_ptr<class xxx>::~smart_ptr<class xxx>(); //calling smart pointer
destructor gives error
return 0;
}
I am getting compilation errors while compiling this file because of wrong copy constructor, assignment operator and destructor codes.
The errors are:
smart_pointer_impl.cpp: In function ‘int main(int, char**)’:
smart_pointer_impl.cpp:33: error: ‘smart_ptr<xxx>’ is not a base of ‘xxx’
smart_pointer_impl.cpp: In copy constructor ‘smart_ptr<t>::smart_ptr(const
smart_ptr<t>&) [with t = xxx]’:
smart_pointer_impl.cpp:28: instantiated from here
smart_pointer_impl.cpp:8: error: passing ‘const smart_ptr<xxx>’ as ‘this’ argument
of ‘t*
smart_ptr<t>::operator->() [with t = xxx]’ discards qualifiers
smart_pointer_impl.cpp:8: error: ‘class xxx’ has no member named ‘ptr’
Please find where I am wrong in the above functions. Any help is welcome.
One obvious error is that your assignment operator should take and return references to smart_ptr, not t:
smart_ptr& operator = (const smart_ptr& lhs)
//^^^^^^^^^ ^^^^^^^^^
Next, your copy constructor calls sm->ptr when it should be calling sm.ptr, since -> has been overloaded to return a t anyway:
smart_ptr(const smart_ptr& sm) : ptr(sm.ptr) { .... }
Compilation errors could be fixed with the following changes:
// copy ctor
smart_ptr(const smart_ptr &sm)
: ptr(sm.ptr)
{
cout<<"copy constructor is called" << endl;
}
// destructor's invocation
p2.~smart_ptr();
However there's a logic error in the copy constructor as the underlying object will be deleted twice (or more times).