#include <vector>
using namespace std;


template< typename TBufferTypeFront, typename TBufferTypeBack = TBufferTypeFront>
class FrontBackBuffer {

public:

    template <typename T>
    struct MyRefTypes {
        typedef const T & Con;
        typedef T& Ref;
        typedef const T& CRef;
        static Ref getRef(T& v) {
            return v;
        }
    };

//Specialization for Reference
    template <typename T>
    struct MyRefTypes<T&> {
        typedef T & Con;
        typedef T& Ref;
        typedef const T& CRef;
        static inline Ref getRef(T& v) {
            return v;
        }
    };

//Specialization for const Reference
    template <typename T>
    struct MyRefTypes<const T&> {
        typedef const T & Con;
        typedef const T& Ref;
        typedef const T& CRef;
        static inline Ref getRef(const T& v) {
            return v;
        }
    };

//Specialization for const
    template <typename T>
    struct MyRefTypes<const T> {
        typedef const T & Con;
        typedef const T& Ref;
        typedef const T& CRef;
        static inline Ref getRef(const T& v) {
            return v;
        }
    };

//Specialization for pointers
    template <typename T>
    struct MyRefTypes<T*> {
        typedef T* Con;
        typedef T& Ref;
        typedef T* const CRef;  //! note this is a pointer....
        static inline Ref getRef(T* v) {
            return *v;
        }
    };

//Specialization for const pointers
    template <typename T>
    struct MyRefTypes<const T*> {
        typedef const T* Con;
        typedef const T& Ref;
        typedef const T* const CRef; //! note this is a pointer....
        static inline Ref getRef(const T* v) {
            return *v;
        }
    };


    typedef typename MyRefTypes<TBufferTypeFront>::Ref TBufferTypeFrontRef;
    typedef typename MyRefTypes<TBufferTypeFront>::CRef TBufferTypeFrontCRef;
    typedef typename MyRefTypes<TBufferTypeFront>::Con TBufferTypeFrontCon;

    typedef typename MyRefTypes<TBufferTypeBack >::Ref TBufferTypeBackRef;
    typedef typename MyRefTypes<TBufferTypeBack >::CRef TBufferTypeBackCRef;
    typedef typename MyRefTypes<TBufferTypeBack >::Con TBufferTypeBackCon;

    // Remove reference because const T & yields with T = int&  -> int&
    explicit FrontBackBuffer(
        TBufferTypeFrontCon  m_front,
        TBufferTypeBackCon   m_back):
        m_Front(m_front),
        m_Back(m_back)
    {
    };


    ~FrontBackBuffer()
    {};

    TBufferTypeFrontRef getFront() {
        return MyRefTypes<TBufferTypeFront>::getRef(m_Front);
    }
    TBufferTypeBackRef getBack() {
        return MyRefTypes<TBufferTypeBack>::getRef(m_Back);
    }
    private:

    TBufferTypeFront m_Front;       ///< The front buffer
    TBufferTypeBack m_Back;         ///< The back buffer

};


typedef std::vector<float> GAGAType ;

int main() {
    int aa = 7;
    FrontBackBuffer<int&, double> a(aa,7);
    //a.getFront() = 4 //COmpile error! OK!;
    a.getBack() = 4;
    
    const int r = 7;
    FrontBackBuffer<const int&, std::vector<int> > a1(r, std::vector<int>(7));
    //a.getFront() = 4 //COmpile error! OK!;
    a1.getBack()[0] = 4;
    
    int bb;
    GAGAType bbb;
    FrontBackBuffer< int*, GAGAType * > b(&bb, &bbb);
    b.getBack().push_back(0);
    b.getFront() = int (4);
    
}