0

今天早上我遇到了这个问题:

我想构建一个通用类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_pFrontvoid *m_pBack我应该用它们来完成这项工作,并正确分配(参见构造函数)。

但是我现在如何编写这些 getter 函数对我来说是个谜:

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

归根结底,它应该可以正常工作:-)感谢您的帮助并尝试解决这个难题:-)!

4

2 回答 2

0

这是完整的答案!

代码有效,缓冲区是通用的 :-) --> http://ideone.com/m3kFmo

并且交换功能也很有效并且可以按需要工作!

当然这个类只有在底层类型相同时才有用FrontBackBuffer< int *, int &>--> OK

FrontBackBuffer< int *, const double &>--> 没问题,但是交换功能没有意义!

代码在这里!:-)

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 T Org;
        typedef T* Ptr;
        typedef const T & Con;
        typedef T& Ref;
        typedef const T& CRef;
        static inline Ptr getUnderlyingPtr(T& v) {
            return &v;
        }
        static Ref getRef(T& v) {
            return v;
        }
    };

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

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

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

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

    //Specialization for const pointers
    template <typename T>
    struct MyRefTypes<const T*> {
        typedef T Org;
        typedef T* Ptr;
        typedef const T* Con;
        typedef const T& Ref;
        typedef const T* const CRef; //! note this is a pointer....
        static inline Ptr getUnderlyingPtr(const T* v) {
            return const_cast<T*>(v);
        }
        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<TBufferTypeFront>::Org TBufferTypeFrontOrg;
    typedef typename MyRefTypes<TBufferTypeFront>::Ptr TBufferTypeFrontPtr;

    typedef typename MyRefTypes<TBufferTypeBack >::Ref TBufferTypeBackRef;
    typedef typename MyRefTypes<TBufferTypeBack >::CRef TBufferTypeBackCRef;
    typedef typename MyRefTypes<TBufferTypeBack >::Con TBufferTypeBackCon;
    typedef typename MyRefTypes<TBufferTypeBack >::Org TBufferTypeBackOrg;
    typedef typename MyRefTypes<TBufferTypeBack >::Ptr TBufferTypeBackPtr;

    explicit FrontBackBuffer(
                             TBufferTypeFrontCon  front,
                             TBufferTypeBackCon   back):
    m_Front(front),
    m_Back(back)
    {
        m_pBack = MyRefTypes<TBufferTypeBack>::getUnderlyingPtr(m_Back);
        m_pFront = MyRefTypes<TBufferTypeFront>::getUnderlyingPtr(m_Front);

    };


    ~FrontBackBuffer()
    {};

    TBufferTypeFrontRef getFront() {
        return *m_pFront;
    }
    TBufferTypeBackRef getBack() {
        return *m_pBack;
    }

    void swap(){
        TBufferTypeFrontPtr temp = m_pFront;
        m_pFront = m_pBack;
        m_pBack = temp;
    }

private:



    TBufferTypeFrontPtr m_pFront;       ///< The pointer to front buffer
    TBufferTypeBackPtr  m_pBack;         ///< The pointer to back buffer

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

};

我们现在可以这样使用它:

int main() {
        int front=10;
    int back=3;
    FrontBackBuffer< const int*, int & > buf1(&front, back);
    buf1.getBack() = 4; // change from 3 to 4
    // buf.getFront() = 5; NO! is const!
    buf1.swap();
        std::cout << buf1.getFront() << buf1.getBack() << std::endl;
    //NOW getBack() and getFront() should return  4 and 10!

        front = 1;
        back= -1;
    FrontBackBuffer<int &, int > buf2(front, back);
    buf2.getBack() = 2; 
    buf2.getFront() = 3; 

    buf2.swap();   
    //NOW getBack() and getFront() should return  2 and 3!
    std::cout << buf2.getFront() << buf2.getBack() << std::endl;

        front = 1;
        back= -1;
    FrontBackBuffer<int, const int &> buf3(front, back);
    //buf3.getBack() = 2; // IS CONST!!
    buf3.getFront() = 3; 

    buf3.swap();   
    //NOW getBack() and getFront() should return  -1 and 3!
    std::cout << buf3.getFront() << buf3.getBack() << std::endl;

}
于 2012-11-09T10:39:11.590 回答
0

我必须承认我真的不明白为什么您需要发布的所有代码才能完成您描述的任务,但我可能遗漏了一些东西。但是考虑到您只想以通用但有效的方式交换两个相同类型的缓冲区,我建议如下:

template<typename BufferType>
class FrontBackBuffer
{
private:
    BufferType buffers[2];
    int _back,_front;
public:
/*
omitting copy constructors, operators etc for brevity
*/
    FrontBackBuffer()
        : _front(0), _back(1)
    {
         /*
           You can also start with front and back pointing to the same memory it is of no  importance if you remember to swap them once or if you just set the back buffer and never the front
         */
    }
    BufferType & getFront()
    {
        return buffers[_front];
    }
    BufferType & getBack()
    {
        return buffers[_back];
    }
    void swap()
    {
        _front = _back;
        _back = (_front + 1) % 2;
    }
};

你可以像这样使用它:

int intArray[] = {1,2,3,4};

FrontBackBuffer<int*> intPtrBuffers;
intPtrBuffers.getBack() = new int[4];
intPtrBuffers.getFront() = new int[4];

memcpy(intPtrBuffers.getBack(), intArray, sizeof(intArray));
intPtrBuffer.swap();
于 2012-11-10T17:32:56.217 回答