沒有辦法遍歷結構的成員而沒有全部列出。
您可以在編譯時使用C++ 11中的::std::tuple
來遍歷類似結構的東西。
您也無法真正地以這種方式打開類型。你可以這樣做,但是你的做法是有幾個具有相同名稱的函數,每個函數採用不同的參數類型。喜歡的東西:
void doRead(StreamType &stream, int &data)
{
data = stream.readInt32();
}
void doRead(StreamType &stream, char &data)
{
data = stream.readChar();
}
// etc...
然後你只需要調用doRead
與結構成員和噗編譯神奇挑選基於該類型是正確的。
在C++中,解決您在這裏解決的問題的方法是序列化庫。如果您可以控制寫入的格式和讀取的格式,則可以使用類似protobuf或boost::serialization的東西來相對簡單地完成此操作,而無需編寫大量自己的代碼。
此外,您的代碼有幾個問題。不要在標識符中使用前導_
字符。帶有前導_
的標識符被保留供編譯器或標準庫實現使用。許多編譯器都有特殊的關鍵字,這些關鍵字是以_
字符開頭的編譯器特定語言擴展。使用帶有前導字符_
的標識符可能會導致代碼神祕地無法在某些環境中編譯各種奇怪的難以理解的錯誤。
你可以得到類似於在編譯時可枚舉的結構的東西。但它的醜陋:
#include <tuple>
#include <string>
#include <vector>
#include <type_traits>
class asset : public ::std::tuple< ::std::string, ::std::vector<BYTE> >
{
public:
::std::string &name() { return ::std::get<0>(*this); }
const ::std::string &name() const { return ::std::get<0>(*this); }
::std::vector<BYTE> &data() { return ::std::get<1>(*this); }
const ::std::vector<BYTE> &data() const { return ::std::get<1>(*this); }
};
void writeToStream(Stream *out, const ::std::string &field)
{
out->writeString(field);
}
void writeToStream(Stream *out, const ::std::vector<BYTE> &field)
{
out->writeInt(field.size());
out->writeRaw(field.data(), field.size());
}
template <unsigned int fnum, typename... T>
typename ::std::enable_if< (fnum < sizeof...(T)), void >::type
writeToStream_n(Stream *out, const::std::tuple<T...> &field)
{
writeToStream(out, ::std::get<fnum>(field));
writeToStream_n<fnum+1, T...>(out, field);
}
template <unsigned int fnum, typename... T>
typename ::std::enable_if< (fnum >= sizeof...(T)) >::type
writeToStream_n(Stream *, const::std::tuple<T...> &)
{
}
template <typename... Tp>
void writeToStream(Stream *out, const ::std::tuple<Tp...> &composite)
{
writeToStream_n<0, Tp...>(out, composite);
}
void foo(Stream *out, const asset &a)
{
writeToStream(out, a);
}
注意,沒有爲asset
類型沒有明確writeToStream
。編譯器會在運行時通過解壓它從每個字段派生出來並寫出它來編寫它。另外,如果你有裸指針,那麼你正在編寫不好的C++。如果你要編寫C++,請寫出慣用的,好的C++。你想用運行時反射來做這件事情不是做事情的方式。
這就是我之所以轉變你的char *name
爲::std::string
和你的尺寸界定你size
和data
領域代表爲::std::vector
陣列。使用這些類型是編寫C++的慣用正確方法。使用裸指針的方式不是。此外,如果有兩個具有強相關值的字段(data
和size
)字段沒有任何行爲或任何其他關聯指示,那麼即使對於在運行時進行自省的編譯器來說,也很難找出正確的事情做。它不知道data
指向的陣列有多大,並且它不知道您在size
中對此編碼的決定。
C++中沒有反射。 – 2013-03-09 01:47:27
@YochaiTimmer:這不完全正確。有一種編譯時反射。在一個模板中,我可以問「這個類型是否支持'push_back'操作?」。但嚴格來說在編譯時,而不是運行時。 'typeof'運算符支持基本運行時'反射'。但它不是很強大。 – Omnifarious 2013-03-09 01:53:46
C或C++語言不支持反射的概念,即在運行時反演對象以確定類型及其結構。 C++支持使用RTTI的一種簡單的內省方式,但與您正在尋找的內容相比,它非常有限。如果您對此感興趣,請閱讀'typeid'更多信息 – Tuxdude 2013-03-09 01:54:09