代码之家  ›  专栏  ›  技术社区  ›  Andrew Goedhart

使用包装对象作为具有可变模板和参考参数的右值

  •  0
  • Andrew Goedhart  · 技术社区  · 7 年前

    我有一个可变模板函数

    template<typename ...ARGS>
    inline void ReadStream::decode(ARGS&...args) {
       internalDecode(args...);
    }
    
    template<typename T, typename ...ARGS>
    inline void ReadStream::internalDecode(T &head, ARGS&...args) {
      read(head);
      internalDecode(args...);
    }
    
      inline void ReadStream::internalDecode() {
      }
    

    这让我可以写作

    int a, b;
    ByteArray c;
    String d
    
     x.decode(a,b,c,d);
    

    将传入的二进制流解包为一组变量,而不使用锅炉板。

    我实现了一个包装器对象“FixedSize”,它更改了特定变量的读取/解码默认格式。

     template <typename T>
     class FixedSize{
         T &value;
         uint16_t  length;
    
      public:
    
         FixedSize(T &wrapped, uint32_t size):
           value(wrapped),
           length(static_cast<uint16_t>(size)){
         }
    
         template< typename STREAM>
         void read(STREAM &stream){
           stream.readBytes(value, 0, length);
           value.setLength(length);
         }
    
      };
    
      template<typename T>
      FixedSize<T> fixedSizeField(T &field, uint32_t length){
         return FixedSize<T>(field, length);
      }
    

    理论上,这将允许像这样调用解码

     x.decode(a,b,fixedSize(c,16), d);
    

    然而,fixedSize()返回的对象现在是一个右值,编译器不允许使用

    “FixedSize&类型的非常量引用的初始化无效”从右值。。。。

    因为RValue包含对底层对象的引用,如果编译器允许我编译它,那么这段代码实际上可以工作。事实上,如果我创建一个FixedSize类型的对象,然后像这样将其传递给解码函数,它就会工作。

     auto e = fixedSize(c,16)
     x.decode(a,b, e, d)
    

    我该如何强制编译器接受作为右值返回的包装器对象?

    2 回复  |  直到 7 年前
        1
  •  1
  •   lorro    7 年前

    不要;到处转发参数(通过获取Args和通过std::forward(Args)…),除了在头部,并使过载。观察包装可能是常量;所以你可以把它当成常数&并且仍然通过引用修改目标。

    此外,正如我所见,您不需要单独使用decode()和internalDecode;只需保留internalDecode()并将其命名为decode()。

        2
  •  0
  •   Andrew Goedhart    7 年前

    根据Iorro的评论,这是使用通用引用、转发和函数重载的工作代码:

    template<typename T, typename ...ARGS>
    inline void ReadStream::decode(T &head, ARGS&&...args) {
      read(head);
      decode(std::forward<ARGS>(args)...);
    }
    
    template<typename T, typename ...ARGS>
    inline void ReadStream::decode(const T &head, ARGS&&...args) {
      read(head);
      decode(std::forward<ARGS>(args)...);
    } 
    
    inline void ReadStream::decode() {
    }
    

    此外 阅读 中的函数 固定包装器 需要构造,即

     template< typename STREAM>
     void read(STREAM &stream) const {
       stream.readBytes(value, 0, length);
       value.setLength(length);
     }    
    

    x.decode(a,b,fixedSize(c,16), d);
    

    这是因为可以将右值传递给重载函数taking(const T,…)一切都在编译和运行。