The following three source files is to define and test a class StackLayer.While it was written in a need for scalable layer-based architecture design, it was also a practice for std::shared_ptr (I'm new to C++11).I'm not sure if I'm understanding the concept and best practices for std::weak_ptr and std::shared_ptr.You will notice that the LayerNode struct is completely public to derived classes, which I couldn't avoid because of some error std::shared_ptr was complaining about (conversion exists but inaccessible).  I don't like this because it ruins all the encapsulation.I'm also not sure if I have any memory leak or not (at least it is not breaking).To prevent lower layer to access higher layer, I also had to make GetLayer function return null if that case happens. Should I assert or throw on this case instead of returning nullptr?I only tested it in Visual C++ CPT120 (might have missing 'typename' errors in gcc, or not if I get lucky)Singleton.htemplate<typename Derived>class Singleton{public:    // Getter    static Derived& GetInstance( void )    {        static Derived s_instance;        return s_instance;    }protected:    // Ctor    Singleton( void ){}    // Dtor    virtual ~Singleton( void ){}private:    // NO COPY    Singleton( const Singleton& rhs );    // NO ASSIGNMNET    Singleton& operator=( const Singleton& rhs );}; // class SingletonLayerStack.h#ifndef LAYER_STACK_INCLUDE_GUARD#define LAYER_STACK_INCLUDE_GUARD#include Singleton.h      // Singleton#include <vector>           // std::vector#include <memory>           // std::shared_ptr std::weak_ptr std::dynamic_casting#include <unordered_map>    // std::unordered_map#include <cassert>          // assert#include <type_traits>      // std::is_pointer#include <algorithm>        // std::for_each#include <functional>       // std::functionclass LayerStack;// public Inherit this class to make a layer.// layer is to be added to an instance of LayerStack before calling GetLayer function.(Look at LayerStack::Push function)template <typename Derived>class Layer : public LayerStack::LayerNode, public Singleton<Derived>{    friend class LayerStack;public:    typedef Derived instance_type;    Layer( void )        : LayerNode( typeid(Derived).hash_code() )        , Singleton()    {    }    template <typename T>    std::shared_ptr<T> GetLayer( void )    {        return LayerNode::m_pLayerStack->QueryLayerFrom<T>(m_attitue);    } // std::shared_ptr<T> GetLayer( void )    virtual ~Layer( void ) {}}; // class Layer : public LayerStack::LayerNode, public Singleton<Derived>// Layer Stack.// Can store instance of layer inheriting class Layer.// These rules are to be followred://      * Each type of layer can only appear once in the same layer stack.( Layer is Singleton. Look at Layer definition )//      * Layer can access other layer by calling GetLayer function, but not in ascending order( Only layer pushed eairler than caller layer can be accessed. In other words, top layer can acess all layers, while bottom layer cannot access any layer)class LayerStack{    template <typename Derived>    friend class Layer;private:    typedef std::size_t type_hash_type;    typedef std::size_t size_type;    struct LayerNode    {        LayerNode( type_hash_type typeHash )            : m_pLayerStack(nullptr)            , m_typeHash(typeHash)            , m_attitue(0)        {        }        virtual ~LayerNode( void ) {}        LayerStack*                 m_pLayerStack;        LayerStack::type_hash_type  m_typeHash;        int                         m_attitue;    };public:    typedef std::unordered_map<type_hash_type, std::weak_ptr<LayerNode>> layer_map_type;    typedef std::vector<std::shared_ptr<LayerNode>> layer_vec_type;private:    layer_map_type m_layerMap;    layer_vec_type m_layerVec;public:    LayerStack( void )        : m_layerMap()        , m_layerVec()    {    }    template <typename T>    void Push( std::shared_ptr<T>&& item )    {        static_assert(!std::is_pointer<T>::value, Cannot use a shared pointer to a pointer);        // Gets type hash code        type_hash_type h = typeid(T).hash_code();        // Search item by the hash code from the map.        // item shouldn't be duplicate(Singleton)        assert(m_layerMap.find(h) == m_layerMap.end());        // Set Parent pointer        item->m_pLayerStack = this;        // Add item to the vector        m_layerVec.push_back(item);        // Add item to the map        m_layerMap[h] = item;        // Set attitue        item->m_attitue = m_layerVec.size();    } // void Push( std::shared_ptr<T>&& item )    void Pop( void )    {        m_layerMap.erase(m_layerVec.back()->m_typeHash);        m_layerVec.pop_back();    } // void Pop( void )    template <typename CAST_TYPE>    void ForAscendingEach( std::function<void(CAST_TYPE*)> callback)    {        std::for_each( m_layerVec.begin(), m_layerVec.end(), [&]( std::shared_ptr<LayerNode> spNode )        {            callback(std::dynamic_pointer_cast<CAST_TYPE>(spNode).get());        });    }    template <typename CAST_TYPE>    void ForDescendingEach( std::function<void(CAST_TYPE*)> callback)    {        std::for_each( m_layerVec.rbegin(), m_layerVec.rend(), [&]( std::shared_ptr<LayerNode> spNode )        {            callback(std::dynamic_pointer_cast<CAST_TYPE>(spNode).get());        });    }    template <typename CAST_TYPE, typename ...Args>    void ForAscendingEach( void (CAST_TYPE::*callback)(Args...) , Args... args)    {        std::for_each( m_layerVec.begin(), m_layerVec.end(), [&]( std::shared_ptr<LayerNode> spNode )        {            (std::dynamic_pointer_cast<CAST_TYPE>(spNode).get()->*callback)(args...);        });    }    template <typename CAST_TYPE, typename ...Args>    void ForDescendingEach( void (CAST_TYPE::*callback)(Args...) , Args... args)    {        std::for_each( m_layerVec.rbegin(), m_layerVec.rend(), [&]( std::shared_ptr<LayerNode> spNode )        {            (std::dynamic_pointer_cast<CAST_TYPE>(spNode).get()->*callback)(args...);        });    }    size_type Size( void )    {        return m_layerVec.size();    } // size_type Size( void )    template <typename T>    std::shared_ptr<T> QueryLayer( void )    {        assert( m_layerMap.find(typeid(T).hash_code()) != m_layerMap.end() );        return std::dynamic_pointer_cast<T>(m_layerMap[typeid(T).hash_code()].lock());    }private:    template <typename T>    std::shared_ptr<T> QueryLayerFrom( int attitue )    {        assert( m_layerMap.find(typeid(T).hash_code()) != m_layerMap.end() );        return m_layerMap[typeid(T).hash_code()].lock()->m_attitue < attitue            ? std::dynamic_pointer_cast<T>(m_layerMap[typeid(T).hash_code()].lock())            : nullptr;     }}; // class LayerStackMain.cpp#include LayerStack.h#include <iostream>#define PROMPT(MSG) do { std::cout <<  *  << (MSG) << std::endl; } while(0)#define SHOW(EXPR) do { std::cout << (#EXPR) <<  :  << (EXPR) << std::endl; } while(0)class Base{public:    virtual ~Base( void ){}    virtual void Print( void ) = 0;    virtual void PrintInt( int i ) = 0;};class A : public Layer<A>, public Base{public:    virtual void Print( void ) override    {        std::cout << A Printing << std::endl;    }    virtual void PrintInt( int i ) override    {        std::cout << A Printing  << i << std::endl;    }};class B : public Layer<B>, public Base{public:    virtual void Print( void ) override    {        std::cout << B Printing << std::endl;    }    virtual void PrintInt( int i ) override    {        std::cout << B Printing  << i << std::endl;    }};void PrintBase( Base* pBase ){    pBase->Print();}int main( void ){    LayerStack stack;    PROMPT(Pushing A);    stack.Push( std::make_shared<A>() );    SHOW(stack.Size());    PROMPT(Pushing B);    stack.Push( std::make_shared<B>() );    SHOW(stack.Size());    PROMPT(Now Stack Looks like:);    PROMPT(  [Top] B);    PROMPT(  [Bottom] A);    PROMPT(Query A Directly from the stack layer);    std::shared_ptr<A> sptra;    SHOW(sptra = stack.QueryLayer<A>());    PROMPT(Query B Directly from the stack layer);    std::shared_ptr<B> sptrb;    SHOW(sptrb = stack.QueryLayer<B>());    PROMPT(Call function in ascending order);    stack.ForAscendingEach<Base>(PrintBase);    PROMPT(Call function in descending order);    stack.ForDescendingEach<Base>(PrintBase);    PROMPT(Call member function in ascending order);    stack.ForAscendingEach<Base>(&Base::PrintInt, 1);    PROMPT(Call member function in descending order);    stack.ForDescendingEach<Base>(&Base::PrintInt, 2);    PROMPT(Accessing A from B should success(A is lower than B.(A is pushed eairlier) descending access is allowed));    SHOW(sptra = sptrb->GetLayer<A>());    PROMPT(Accessing B from A should fail(B is higher than A.(B is pushed later) ascending access is prevented.));    SHOW(sptrb = sptra->GetLayer<B>());    PROMPT(Popping A);    stack.Pop();    SHOW(stack.Size());    PROMPT(Popping B);    stack.Pop();    SHOW(stack.Size());    return 0;} // int main( void )Output: * Pushing Astack.Size() : 1 * Pushing Bstack.Size() : 2 * Now Stack Looks like: *   [Top] B *   [Bottom] A * Query A Directly from the stack layersptra = stack.QueryLayer<A>() : 01009074 * Query B Directly from the stack layersptrb = stack.QueryLayer<B>() : 0100D544 * Call function in ascending orderA PrintingB Printing * Call function in descending orderB PrintingA Printing * Call member function in ascending orderA Printing 1B Printing 1 * Call member function in descending orderB Printing 2A Printing 2 * Accessing A from B should success(A is lower than B.(A is pushed eairlier) descending access is allowed)sptra = sptrb->GetLayer<A>() : 01009074 * Accessing B from A should fail(B is higher than A.(B is pushed later) ascending access is prevented.)sptrb = sptra->GetLayer<B>() : 00000000 * Popping Astack.Size() : 1 * Popping Bstack.Size() : 0
Layer Stack class to practice std::shared_ptr
c++;c++11;inheritance;stack;smart pointers
Some minor things:Include guard names don't need an _INCLUDE_GUARD at the end.  They should not be confused with macros anyway, although you won't have very many of them in C++.Consider organizing your library #includes, such as alphabetically.  This will make it easier to keep track of all of them.Comments like //Ctor and //Dtor are noise since it's already obvious.  Comments shouldn't point out the obvious; they should provide useful information.Since your types are named in PascalCase, name your functions in camelCase or snake_case.  It's generally good to use separate naming types for these two things.All the std::endls can be replaced with \n.  You don't need to flush the buffer so many times (which is what the former also does), and the latter will just output a newline.You don't need an explicit return 0 at the end of main().  Successful termination is already implied at this point, so the compiler will do this return for you here.You don't need a comments after a closing brace, especially at the end of main().  It may be okay if you have many nested ones, but it's just clutter for others.Unlike in C, a void parameter is not needed for functions taking no arguments.