1) Стандарт гарантирует, что sizeof(char) == 1
2) В с++, к сожалению, не так много встроенных хороших способов обработки ошибок, поэтому лучше использовать исключения. Они понятны всем, не придется создавать CFB::CompoundFileReader в случае ошибки в GetReader и не будет простыни из if-ов на каждый вызов функции. Но не забывай очищать память и закрывать файлы перед бросанием исключения. Лучше пользоваться
RAII.
3) Smart pointer-ы на самом деле не такие уж и плохие менеджеры памяти, почему бы не использовать их. Из ReadStream можно просто возвращать unique_ptr, а в случае с буффером для CFR, если их время жизни должно совпадать, то почему бы не хранить их вместе.
class ReaderWatcher {
public:
ReaderWatcher(std::shared_ptr<unsigned char[]> b, size_t len)
: buffer(std::move(b)), reader(b.get(), len) {}
Reader* operator ->() {
return &reader;
}
Reader get() {
return reader;
}
private:
std::shared_ptr<unsigned char[]> buffer {nullptr};
Reader reader;
};