I had an assignment to create a table that will be stored in ROM (read only) and will be used in some algorithms (to convert numbers to strings). However sometimes a user will want to edit the table a bit before using it in the algorithms. So the user must be able to copy the table to RAM, change it and then use it. With this in mind I have come up with the following code. Note: This is a simplified version of my code to illustrate the solution. In reality RomClass has more members.Class representing a row in the table:struct Row{    constexpr Row() = default;    constexpr Row(float f, int i) : num_float(f), num_int(i) {}    float num_float = 0;    int num_int     = 0;};Class representing the table in ROM (read only):class RomClass{public:    template <std::size_t N>    constexpr RomClass(const Row (&table)[N])    : m_table(table),      m_size(N)    {    }    std::size_t size() const                    { return m_size; }    const Row& row(std::size_t i) const         { assert(m_size > i);  return m_table[i]; }private:    const Row* m_table  = nullptr;    std::size_t m_size  = 0;    friend class RamClass;};Class used to edit the table. It copies the table to RAM and allows editing. It also has a member that returns a reference to RomClass so it can be used with algorithms.class RamClass{public:    RamClass(const RomClass& rom);    RamClass(const RamClass& rhs);    RamClass& operator= (RamClass rhs);    void swap(RamClass& rhs);    const RomClass& romClass() const        { return m_rom; }  // for algorithms that work with RomClass    std::size_t size() const                { return m_table.size(); }    Row& row(std::size_t i)                 { return m_table[i]; }private:    RomClass m_rom;    std::vector<Row> m_table;};inline void swap(RamClass& lhs, RamClass& rhs){    lhs.swap(rhs);}RamClass::RamClass(const RomClass& rom): m_rom(rom)  // naredimo kopijo{    m_table.resize(rom.m_size);                                                 std::copy(&rom.m_table[0], &rom.m_table[rom.m_size], &m_table[0]);          m_rom.m_table = &m_table[0];}RamClass::RamClass(const RamClass& rhs): m_rom(rhs.m_rom),  m_table(rhs.m_table){    const Row*& table = *const_cast<const Row**>(&m_rom.m_table);             table = &m_table[0];}RamClass& RamClass::operator=(RamClass rhs){    this->swap(rhs);    return(*this);}void RamClass::swap(RamClass& rhs){    using std::swap;    swap(m_table, rhs.m_table);    auto lhsTable = m_rom.m_table;    auto rhsTable = rhs.m_rom.m_table;    swap(lhsTable, rhsTable);}Algorith function would look something like:void algorithm(const RomClass& rom){    for (auto i = 0; i < rom.size(); ++i)    {        // do sth    }}Usage:    constexpr Row romTable[] ={    Row(19.99F, 2),    Row(2.3F, 4),    Row(),  // end element};constexpr RomClass romClass ={    romTable};int main(){    RamClass ramClass = romClass;    ramClass.row(0).num_float = 9000;    // allows editing    romClass.row(0).num_float = 9000;    // error    RomClass romClass2(romTable);    romClass2.row(0).num_float = 9000;  // also an error    return 0;}Ideally I would want to ditch the RamClass and just have a RomClass that would also have non-const member functions that would expose the table and allow editing. But then the following code would not produce an error:RomClass romClass2(romTable);romClass2.row(0).num_float = 9000;  // not an error, but it should beI would appreciate any improvements that I could do with this code while achieve the goals I posted above and be as user friendly as possible - not allow to accidentally edit read only data.
ROM / RAM table
c++;c++11