我有一个可变参数模板函数
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的包装器对象?
答案 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;,...)并且所有内容都编译并运行。