Здравствуйте, Tscheineg, Вы писали:
T>Но меня ждал еще один сюрприз: MSVC все равно не сообщает об ошибке, так что вся эта затея обломилась. Как-то можно заставить компилятор замечать такие явные ошибки?
Есть смысл отказаться от голого сишного массива char(&)[N] в пользу полноценного типа boost::array<char,N> или чего-то в таком роде.
Тогда можно заставить ошибки ловиться в рантайме.
template<class T>
class proxy_array
{
T* arr_;
size_t n_;
public:
proxy_array(T* arr, size_t n) : arr_(arr), n_(n) {}
T& operator[](int i) const { assert(i>=0 && i<n_); return arr_[i]; }
/////////////////////
T* data() const { return arr_; }
size_t size() const { return n_; }
// при желании - можно прикрутить итераторы с отладочными средствами
};
TData Parse(proxy_array<char> Buf)
{
int i=0;
char c0 = Buf[i++];
char c1 = Buf[i++];
....
char c5 = Buf[i++]; // assertion fault!
....
}
TData Read(char* Msg, int Len)
{
return Parse(proxy_array<char>(Msg,Len));
}
T>Еще обнаружил, что если строку #2 слегка изменить:
T>const TBufArr &BufArr=reinterpret_cast<const TBufArr&>(Msg+1);
T>то возникает ошибка error C2102: '&' requires l-value
T>В чем тут дело?
Дело в том, что реинтерпрет ссылки — это попытка трактовать переменную, а не её значение.
Msg+1 — это значение типа char*, существующее только мысленно.
Msg[1] — это переменная типа char, находящаяся по адресу Msg+1
Вот (ссылку на) эту переменную (плюс следующие за ней несколько байтов) уже можно трактовать как (ссылку на) переменную иного типа.
А (указатель на) — можно трактовать как (указатель на).
То есть
const TBufArr* pBuf = reinterpret_cast<const TBufArr*>( Msg+1 );
const TBufArr& rBuf = *pBuf // или, что то же самое,
*reinterpret_cast<const TBufArr*>( Msg+1 )
reinterpret_cast<const TBufArr&>(*(Msg+1) )
reinterpret_cast<const TBufArr&>( Msg[1] )