I came across this problem this morning:
I want to build a generic class FrontBackBuffer which I can use as the following (some examples).
EDIT Removed some confusing part!
int bb=10;
int fb=3;
FrontBackBuffer< const int*, int & > buf(&fb, &bb);
buf.getBack() = 4; // change from 10 to 4
// buf.getFront() = 5; NO! is const!
buf.swap();
//NOW getFront() and getBack() should return 4 and 3!
FrontBackBuffer< int, const & int > buf(14, bb);
buf.getBack() = 5; // change from 4 to 5
// buf.getFront() = 5; NO! is const!
buf.swap();
//NOW getFront() and getBack() should return 5 and 14!
It stores two buffers, should be of the same underlying type (see the static_assert).
These buffers can be of pointer type or reference type and also const or non const.
It has two functions getFront()and getBack(). These functions always return a reference to the underlying buffer, either const or non-const. That is why there are all sorts of MyRefTypes traits spezialization.
The class which works so far is as the following:
template< typename TBufferTypeFront, typename TBufferTypeBack = TBufferTypeFront>
class FrontBackBuffer {
// If <const * int , int&> --> this result in is_same< int , int >
// STATIC_ASSERT( std::is_same< RemoveModifiers<TBufferTypeFront>::type, typename RemoveModifiers<TBufferTypeFront>::type>::result )
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;
explicit FrontBackBuffer(
TBufferTypeFrontCon front,
TBufferTypeBackCon back):
m_Front(front),
m_Back(back)
{
m_pBack = (void*)&m_Back;
m_pFront = (void*)&m_Front;
};
~FrontBackBuffer()
{};
TBufferTypeFrontRef getFront() {
return MyRefTypes<TBufferTypeFront>::getRef(m_Front);
}
TBufferTypeBackRef getBack() {
return MyRefTypes<TBufferTypeBack>::getRef(m_Back);
}
private:
void swap(){
void * temp = m_pFront;
m_pFront = m_pBack;
m_pBack = temp;
}
TBufferTypeFront * m_pFront; ///< The pointer to front buffer
TBufferTypeBack * m_pBack; ///< The pointer to back buffer
TBufferTypeFront m_Front; ///< The front buffer
TBufferTypeBack m_Back; ///< The back buffer
};
The question is now (which I can not solve completely right):
How can I add a generic function swap() which swaps the buffers, but no copy should be made. I thought about two pointers void * m_pFrontand void *m_pBackwhich I should use to do the job, and assigned correct (see constructor).
But how do I now write these getter functions is a mystery to me:
TBufferTypeFrontRef getFront() {
return MyRefTypes<TBufferTypeFront>::getRef(m_Front);
}
TBufferTypeBackRef getBack() {
return MyRefTypes<TBufferTypeBack>::getRef(m_Back);
}
At the end of the day it should just work 🙂
Thanks for any help and trying to solve this puzzle :-)!
This is the full answer!
The code works and the buffer is generic as hell 🙂 –>
http://ideone.com/m3kFmo
And the swap function is also efficient and works as desired!
Of course this class is only usefull when the underlying type is the same like:
FrontBackBuffer< int *, int &>–> OKFrontBackBuffer< int *, const double &>–> is ok, but swap function makes no sense then!Here the code! 🙂
We are able to use it in this way now: