Stack implementation with shared_ptr C++11 stack.hpp

#ifndef _TOP_HPP
#define _TOP_HPP

#include&lt;memory&gt;
#include&lt;iostream&gt;
#include&lt;cstring&gt;


    template &lt;typename T&gt;
    class Stack{
        private:
            struct Node{
                std::shared_ptr&lt;Node&gt; prev;
                T value;
            };

            int size;
            std::shared_ptr&lt;Node&gt; top;
            const char* name;

        public:
            Stack();
            Stack(const char* name);
            bool isEmpty()const;
            void push(T);
            const int pop();
            const int getSize()const{return size;}
            const char&amp; getName()const{return name;}
            void clear();

            Stack&lt;T&gt;&amp; operator=(const Stack&lt;T&gt;&amp;);
            //don't know why but when implement this friend fun beyond 
            //class then main.cpp don't compile 
            friend std::ostream&amp;  operator&lt;&lt;(std::ostream&amp; os,const Stack&lt;T&gt;&amp; s){
                if(strcmp(s.name,"null")) os&lt;&lt;"Name: "&lt;&lt;s.name&lt;&lt;"  Size "&lt;&lt;s.size&lt;&lt;std::endl;
                auto temp=s.top.get();
                while(temp){
                    os&lt;&lt;temp-&gt;value&lt;&lt;std::endl;
                    temp=temp-&gt;prev.get();
                }
                return os&lt;&lt;std::endl;
            }


    };


    template &lt;typename T&gt;
    inline Stack&lt;T&gt;::Stack():size(0),top(std::make_shared&lt;Node&gt;()),name("null"){ 
        top-&gt;prev=nullptr; 
        top-&gt;value=0; 
    }

    template &lt;typename T&gt;
    inline Stack&lt;T&gt;::Stack(const char* name):size(0),top(std::make_shared&lt;Node&gt;()),name(name){
        top-&gt;prev=nullptr; 
        top-&gt;value=0; 
    }

    template &lt;typename T&gt;
    inline bool Stack&lt;T&gt;::isEmpty()const{
        if(size==0) return true;
        return false;
    }

    template &lt;typename T&gt;
    void Stack&lt;T&gt;::push(T x){
        std::shared_ptr&lt;Node&gt; add =std::make_shared&lt;Node&gt;();
        add-&gt;value=x;
        add-&gt;prev=nullptr;
        if(isEmpty()) top=std::move(add);
        else{
            add-&gt;prev=std::move(top);
            top=std::move(add);
        }
        ++size;
    }

    template &lt;typename T&gt;
    const int Stack&lt;T&gt;::pop(){
        int p=top-&gt;value;
        if(isEmpty()){ std::cerr&lt;&lt;"stack is empty"&lt;&lt;std::endl; }
        else{
            top=top-&gt;prev; //this is good idea ?
            --size;
        }
            return p;
    }


     template &lt;typename T&gt;
     Stack&lt;T&gt;&amp; Stack&lt;T&gt;::operator=(const Stack&lt;T&gt;&amp; s){
         if(this!=&amp;s){
             size=s.size;
             top=s.top;
         }
         return *this;
     }

    template &lt;typename T&gt;
    inline void Stack&lt;T&gt;::clear(){
        while(top){
            top=std::move(top-&gt;prev);i//how can i improve this ? 
            --size;
        }
    }


#endif


main.cpp

#include&lt;iostream&gt;
#include&lt;memory&gt;
#include "stack.hpp"


using namespace std;


int main(){

    Stack&lt;int&gt; s("asd");
    Stack&lt;int&gt; q;
    s.push(12);
    s.push(13);
    s.push(14);
    s.push(15);

    q=s;

    cout&lt;&lt;s; //cout's normal display a stacks 
    cout&lt;&lt;q; 
    s.clear(); // after this fun on s

    cout&lt;&lt;s; // this stack is delete
    cout&lt;&lt;q; // this stack have only 15 (top of stack s) ;/


}
Use containers

Instead of char* name use std::string name, it's safer with the cost of very little overhead, and prevents basic errors like assigning a char string to a pointer, like you do in your constructors, for example:

template &lt;typename T&gt;
inline Stack&lt;T&gt;::Stack(const char* name) :size(0), top(std::make_shared&lt;Node&gt;()), name(name)


You assign a pointer to a pointer, without any control over the lifetime of memory for name, and you'd get undefined behavior when you try to use it.

Always use brackets

Instead of 

if (isEmpty()) top = std::move(add);
else {
    add-&gt;prev = std::move(top);
    top = std::move(add);
}


You should write

if (isEmpty()) {
    top = std::move(add);
}
else {
    add-&gt;prev = std::move(top);
    top = std::move(add);
}


It makes the code more readable and would prevent mistakes that are too easy to miss. There're several places like this in the code.

Your copy constructor is bad

You're not doing a deep copy, but a shallow copy. q gets shared ownership of s stack, you should make a deep copy of it. For example, when you call clear on s, the internal stack gets destroyed, however, q is now in inconsistent state. Here's an example of your stack deep copy

template &lt;typename T&gt;
Stack&lt;T&gt;&amp; Stack&lt;T&gt;::operator=(const Stack&lt;T&gt;&amp; s) {
    if (this != &amp;s) {
        //Creating a new stack
        top = std::make_shared&lt;Node&gt;();

        //Copying the top value
        top-&gt;value = s.top-&gt;value;
        std::shared_ptr&lt;Node&gt; s_stack = s.top;
        top-&gt;prev = std::make_shared&lt;Node&gt;();
        std::shared_ptr&lt;Node&gt; this_prev = top;

        //Copying next values
        while (s_stack-&gt;prev) {
            this_prev = this_prev-&gt;prev;
            s_stack = s_stack-&gt;prev;
            this_prev-&gt;value = s_stack-&gt;value;
            this_prev-&gt;prev = std::make_shared&lt;Node&gt;();
        }

        this_prev-&gt;prev = nullptr;
        size = s.size;
    }
    return *this;
}


Note that further improvements can be made if your Node class would be more intelligent and provide a constructor that would initialize the value, but set the prev pointer to nullptr.

Clear function is bad

After clear the expected behavior is that s is reset to the initial state, that is, top is a shared_ptr to Node object with value = 0, however, after clear method top is a shared_ptr to nullptr. This should be a better implementation that wouldn't mess with other shared owners of internal stack.

template &lt;typename T&gt;
inline void Stack&lt;T&gt;::clear() {
    top = std::make_shared&lt;Node&gt;();
    top-&gt;prev = nullptr;
    top-&gt;value = 0;
    size = 0;
}


However, it requires a correct implementation of copy constructor, since now q memory wouldn't be destroyed, that's what shared_ptr expresses.

PS. You could also gain more insight if you would add a destructor to Node which would output something when a corresponding Node object is destroyed, something like this, but for learning purposes only, it's not a production code in any way.

~Node() {
    std::cout &lt;&lt; "destroyed\n";
}