2013-06-04 31 views
2

我喜欢它,如果有某种的std::istream::read通用版本,所以我可以这样做:std :: istream :: read的通用形式?

ClassA func(std::istream& is) { 
    ClassA a; 
    is.read(a); 
    return a; 
} 

ClassA func(std::istream& is) { 
    return is.read<ClassA>(); 
} 

或甚至:

ClassA::ClassA(std::istream& is) { 
    is.read(data_member); 
} 

但我总是必须补充我自己的通用定义,如下所示:

template< class T > 
void load(T& v, std::istream& is) { 
    is.read((char*)&v, sizeof(v)); 
}; 

template< class T > 
T load(std::istream& is) { 
    T v; 
    is.read((char*)&v, sizeof(v)); 
    return v; 
}; 

在这样做时,我必须提供流作为参数,当它看起来也许它应该是一个流对象的方法。

load(a.data_member, is); 
// vs 
is.read(a.data_member); 

我,也许我在思考这个问题不正确的感觉或者,也许这是愚蠢的,甚至想这样的事情。我认为当编译器能够一般地推断它时,我必须告诉read()读取的大小是愚蠢的。

有没有更好的方法?

+0

你想做什么?通过设置一个值到它的内部数据来创建一个对象是一个UB – Geoffroy

+0

我基本上试图使用'std :: istream :: read'而不必传入读取的大小或使用任何明确的强制转换。这里介绍的一个应用程序是从流中读取字节来构造一个对象。 –

+1

你不应该使用C风格转换('(char *)&v'),而是使用C++风格转换:'reinterpret_cast (&v)'。 – slaphappy

回答

2

没有什么错与您的load功能,只记得它只能与POD类型的作品,所以你应该增加:

static_assert(std::is_standard_layout<T>::value, "A must be a POD type."); 

还有,记得打开例外您的流,否则将无法得到任何错误报告 - 这可能就是为什么流首先不提供这种读取结构的方式。

+0

是的,我可以理解为什么。我想我正在采取这种方向,其中类/结构可以有一个构造函数接受一个流,从它将进行从成员流加载或可能是一个静态方法,默认构造一个,然后做一个成员从流加载。作为额外的好处,这些流有时以网络字节顺序。 –

+0

我会让客户端代码担心他们是否关心流错误;)他们可以在调用load之前打开异常并建立try块。 –

1

一种选择是简单地包装流。这些方针的东西(未测试):

class ObjectStream 
{ 
    std::istream& _is; 
    public: 
    ObjectStream(std::istream& _is) : _is(is) {}; 
    template <class T> 
    ObjectStream& operator>>(T& v) { 
    _is.read((char*)&v, sizeof(T)); 
    return *this; 
    } 
} 

当您打开流,简单地把它的ObjectStream内,并通过周围,而不是你的IStream - 现在你可以通过做stream >> obj只需读取对象,类似于istream重载>>

当然,你也可以只,如果你喜欢使用常规的实例方法。

+0

'operator >>'具有不幸的语义含义,即字符类型和区域设置是相关的。 –

+0

@IronSavior:然后调用'read'方法,你仍然可以做'流'。阅读(OBJ)'。主要的一点是包装让你编写你的代码,以便流看起来可以完成工作,而不是每次都将它作为参数发送。 –

+0

我可以称之为'read',但是我基本上把这个非std :: istream派生的对象看作是'std :: istream'。 –

相关问题