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 :-)!
frontandbackwhen they are the same or their pointers convertible to each other. Be aware thatswaphas a very specific meaning in the standard library and it is different from your meaning. Besides that, what you are trying to achieve doesn't look very useful to me, but I'm probably lacking context.std::pairof pointers where swap is achieved bystd::swap(p.first, p.second)? It is very efficient (moves 24B) and apparently also does what you want. Why are the types of buffers so important? Why is this worth writing a whole new container template?