2013-06-04 59 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'。 –

相關問題