【问题标题】:Template class with get function ALWAYS returning reference,具有获取函数的模板类总是返回引用,
【发布时间】:2012-10-28 20:17:19
【问题描述】:

这里怎么可能有一个模板类被调用

FrontBackBuffer 带模板参数TBackBufferType, TFrontBufferType

template< typename TBufferTypeFront, typename TBufferTypeBack = TBufferTypeFront>
class FrontBackBuffer{
  public:
  explicit FrontBackBuffer(
     TBufferTypeFront const & m_front,
     TBufferTypeBack  const & m_back):
     m_Front(m_front),
     m_Back(m_back)
  {
  };

  ~FrontBackBuffer()
  {};

  typename std::remove_reference<
    typename std::remove_pointer<TBufferTypeFront>::type
  >::type  & getFront(){return m_Front;}    // error: invalid initialization of reference of type 'A&' from expression of type 'A*'| (here T is A)


  typename std::remove_reference<
    typename std::remove_pointer<TBufferTypeBack>::type 
  >::type  & getBack(){return m_Back;}

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

};

我想实现以下目标:

  • 为了在代码中保持一致,无论缓冲区内的类型是什么,我都希望有一个函数 getFront/Back 应该始终返回对缓冲区的引用(一个 const 或一个非 const 取决于类型:例如 const int = T 应该返回一个 const int & 引用!我想写这样的代码

    FrontBuffer<const int&, std::vector<int> > a;
    a.getFront() = 4 //COmpile error! OK!;
    a.getBack()[0] = 4;
    FrontBuffer< int*, GAGAType * > b;
    b.getBack() = GAGAType();
    b.getFront() = int(4);  // this is no ERROR, i would like to get the reference of the memory location pointet by int* ....
    

我想要这样,因为如果我将缓冲区类型从引用更改为指针(我需要取消引用),我想避免更改语法

  • 这样的 Buffer 类是否可以接受所有可能的类型(如 shared_ptr) asd

  • 我想要的只是一些访问权限,它应该非常高效,没有副本等等

  • 我真的不知道如何编写这个通用缓冲区?有人知道吗?

谢谢!!!

EDIT1我还希望能够分配给取消引用的指针:

b.getFront() = int(4);  // this is no ERROR, i would like to get the reference of the memory location pointet by int* ....

这就是我的特质问题所在!

【问题讨论】:

    标签: c++ templates reference


    【解决方案1】:

    您需要专门化 (traits technique) 模板的一部分,如下所示:

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

    更新
    请注意返回引用的特殊功能 - 如果您想对指针采取不同的行为,则需要它 - 为其返回引用。
    结束更新

    并对引用和常量引用进行专门化:

    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;
            }
        };
    

    ((但是我不确定指针的这种专门化是一个好的设计...))


    结束更新

    在你的类模板中使用:

    template< typename TBufferTypeFront, typename TBufferTypeBack = TBufferTypeFront>
    class FrontBackBuffer{
      public:
    
    
       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 m_front,
         TBufferTypeBackCon m_back):
         m_Front(m_front),
         m_Back(m_back)
      {
      };
    
      ~FrontBackBuffer()
      {};
      // See here special functions from traits are used:
      TBufferTypeFrontRef getFront(){return MyRefTypes<TBufferTypeFront>::getRef(m_Front); }    
      TBufferTypeBackRef getBack(){return MyRefTypes<TBufferTypeBack>::getRef(m_Back); }
    
      TBufferTypeFront m_Front;       ///< The front buffer
      TBufferTypeBack m_Back;         ///< The back buffer
    
    };
    

    它按预期工作: http://ideone.com/e7xfoN

    【讨论】:

    • @Gabriel:不要忘记接受 Piotr 的回答,如果它满足你的需要(我自己 +1,顺便说一句)。
    • 嗯,不完全是,我刚刚检查过!我可能没有说清楚,请参阅上面的编辑!
    • @Gabriel - 使用 b.getFront() = new int(4);... 这个new 会有所作为
    • 呵呵,一会儿:我希望当我有一个指针作为底层类型时,即使我调用 getBack() 它也会通过内部指针返回对内存位置指针的引用!我不想将指针设置为新的或更改它:-) 我想要值:-)
    • @Gabriel - 没问题 - 将此注释添加到您的问题中 - 我将更改我的答案,因此它也适用于指针,正如您所愿;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多