【发布时间】:2012-11-08 23:11:03
【问题描述】:
我今天早上遇到了这个问题:
我想构建一个通用类 FrontBackBuffer,我可以将其用作以下(一些示例)。
编辑删除了一些令人困惑的部分!
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!
它存储两个缓冲区,应该是相同的底层类型(参见 static_assert)。
这些缓冲区可以是指针类型或引用类型,也可以是 const 或非 const。
它有两个函数getFront()和getBack()。这些函数总是返回对底层缓冲区的引用,无论是常量还是非常量。这就是为什么会有各种各样的MyRefTypes 特征特殊化。
目前工作的类如下:
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
};
现在的问题是(我不能完全正确地解决):
如何添加通用函数 swap() 来交换缓冲区,但不应复制。我考虑了两个指针void * m_pFront和void *m_pBack,我应该用它们来完成这项工作,并正确分配(参见构造函数)。
但我现在如何编写这些 getter 函数对我来说是个谜:
TBufferTypeFrontRef getFront() {
return MyRefTypes<TBufferTypeFront>::getRef(m_Front);
}
TBufferTypeBackRef getBack() {
return MyRefTypes<TBufferTypeBack>::getRef(m_Back);
}
归根结底,它应该可以工作 :-) 感谢您的帮助并尝试解决这个难题:-)!
【问题讨论】:
-
只有当
front和back相同或者它们的指针可以相互转换时,你才能交换它们。请注意,swap在标准库中具有非常特定的含义,并且与您的含义不同。除此之外,你想要实现的目标对我来说似乎不是很有用,但我可能缺乏上下文。 -
swap 应该做同样的事情,在内部它应该切换缓冲区,不过是一个高效的...
-
我也很困惑你想要完成什么。我假设您知道如果缓冲区的类型不同,则不能交换缓冲区?如果这是正确的,为什么不只存储一个关于它们是否被交换之类的变量。
-
是的,这有点令人困惑,但是如果查看应该如何使用该类的行为,它应该会变得很清楚,下面只是试图实现这一点的一个实现。它可以在没有交换功能的情况下工作......问题是这个缓冲区基本上可以保存自己的内存或引用其他内存(指针或引用),前后都有,这正是好东西,你可以使用它非常通用,它仍然可以做到!但是交换功能是一个难题。这个类只是为了模板的乐趣,可能有点矫枉过正,但不是很好吗?
-
这感觉像是一个错误的设计。简而言之,您的类不是缓冲区,而是指针/引用容器。也许最好解释一下您要完成什么任务以及为什么不能使用
std::pair的指针来完成它,而交换是由std::swap(p.first, p.second)实现的?它非常有效(移动 24B)并且显然也可以满足您的需求。为什么缓冲区的类型如此重要?为什么值得编写一个全新的容器模板?
标签: c++ templates template-specialization traits