I have a kind of buffer class that takes an std::vector as a constructor parameter and uses this vector to storage bytes. This class has methods for reading from and for writing to the buffer. However I would want to give a const std::vector to this buffer class and still be able to use the read functions while write functions should fail at compile time or at least throw an exception.
Only solution that I come up was something like this:
class Buffer
{
public:
Buffer(std::vector<uint8>& vec)
{
this->writeVec = vec
this->readVec = vec;
}
Buffer(std::vector<uint8> const& vec)
{
this->writeVec = null
this->readVec = vec;
}
void write(uint8 i)
{
this->throwIfWriteVecNull();
// do write to writeVec
}
uint8 read()
{
// do read from readVec
}
private:
std::vector<uint8>& writeVec;
std::vector<uint8> const& readVec;
}
Is there any way to achive this without separate writer and reader classes (It would separate similar logic to two different classes which is not nice) and with compile time check for write access? I don't want to use const_casts to any other unsafe hacks. Feel also free to suggest alternative pattern/architecture as a solution.
EDIT:
Thanks all for your answers. From the three answers user315052's facade pattern was closest to something what I wanted, since IMO const_cast or multiple pointers are worse than having few more classes. I also did bit more research and stumbled upon this SO q/a where templates are used to select between const and non-const type. Now I have something like the following and it works perfect, I get "no method error" on compile time if I try to call write on const version. The code got bit ugly beacause of the all templates and stuff but getting errors on compile time is much much better than exceptions.
template <typename BlockType, bool isMutable>
class BaseBuf : boost::noncopyable
{
public:
typedef typename boost::mpl::if_c<isMutable, std::vector<BlockType>, std::vector<BlockType> const>::type VectorType;
BaseBuf(VectorType& blocks) : blocks(blocks)
{
}
void seekReadCursor(size_t pos)
{
// seek to pos
}
bool readBool() const
{
// do read from pos
}
//void read...
//...
protected:
VectorType& blocks;
};
template <typename BlockType>
class ImmuBuf : public BaseBuf<BlockType, false>
{
public:
typedef BaseBuf<BlockType, false> Parent;
typedef typename Parent::VectorType VectorType;
ImmuBuf(VectorType& blocks) : Parent(blocks)
{
}
private:
};
template <typename BlockType>
class MutaBuf : public BaseBuf<BlockType, true>
{
public:
typedef BaseBuf<BlockType, true> Parent;
typedef typename Parent::VectorType VectorType;
MutaBuf(VectorType& blocks) : Parent(blocks)
{
}
// void resize()...
void writeBool(bool b)
{
// do write
}
//void write...
//...
private:
};