将包装器对象用作具有可变参数模板和引用参数的RValues

时间:2017-10-06 13:49:04

标签: c++ pass-by-reference variadic-templates rvalue

我有一个可变参数模板函数

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

将传入的二进制流解压缩为一组没有样板的变量。

我已经实现了一个包装器对象&#39; FixedSize&#39;这会更改读取/解码特定变量的默认格式。

 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()返回的对象现在是一个RValue,并且编译器在允许这个时使用

类型&#39; FixedSize&amp;&#39;的非const引用的无效初始化来自右边......

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

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

我如何强制编译器接受在此返回为rvalue的包装器对象?

2 个答案:

答案 0 :(得分:1)

唐&#39;吨;将参数转发到各处(通过采用Args&amp;&amp; ...并通过std :: forward(args)...),除了头部,并进行重载。观察包装器可能是一个const;所以你可以把它作为一个const&amp;并仍然通过参考修改目标。

另外,我不需要单独解码()和internalDecode;只需保留internalDecode()并将其命名为decode()。

答案 1 :(得分:0)

基于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() {
}

FixedWrapper 中的读取函数也需要设为const

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

现在致电

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

这是有效的,因为Rvalue可以传递给重载函数(const T&amp;,...)并且所有内容都编译并运行。