0

I wanted to make a Table class that is supposed to work like a table with columns and rows, and values in the cells. Obviously I need a function that would allow to get the value from a particular cell. I wanted this function (operator() in my case) to return a reference, so that it would be easy to change the cell's contents.

Now, I wanted to check in this function whether or not such a cell exists (i.e. are there enough columns and rows in the table). The problem is, I can't just return something like a nullptr if col/row index is out of bounds in a function that returns a reference. I've read some other topics on SO and people suggested using optional<reference_wrapper>. Now, the problem is, I can't assign anything to the returned value. Here's the code:

class Table {
public:
    class Column {
    public:
        std::string Header;
        int Index = 0;
        std::vector<std::string> colCells;
        Column(std::string colHeader) { Header = colHeader; }
    };

    std::vector<Column> Columns;
    
    std::optional<std::reference_wrapper<std::string>> operator()(int col, int row) {
        return Columns[col].colCells[row];
    }

    void AddColumn(std::string colHeader) {
        Column col(colHeader);
        col.Index = Columns.size();
        Columns.push_back(col);
        for (auto& row : Columns[0].colCells) { //for each row in the first column (we created a column first, so there's at least this one)
            col.colCells.push_back("");         //create a cell with an empty string    
        }
    }
    void AddRow() {
        for (auto& col : Columns) {
            col.colCells.push_back("");     //add empty string at the end of each column
        }
    }
};

AddColumn and AddRow methods aren't important here, I guess, but I just pasted them here for the code to be complete. Now, I tried this:

data::tbl(4, 0) = "Col: 2, Row: 0";

And that's the errors I get. It seems as if this wasn't an actual reference to the cell's data. I should add that everything works fine the same way if I don't use optional and have the operator enter image description here

What is happening and why?

PS. I know that another way to do all that, would be to change the return value to a pointer. But then I would have to dereference the returned pointer everywhere in the code like this:

*data::tbl(4, 0) = "Col: 2, Row: 0";

Which is something I'd rather avoid if possible.

9
  • 1
    std::optional also has to be dereferenced. It cannot provide direct access to underlying object, since it may be nullopt (like pointer can be nullptr). Commented May 24, 2024 at 16:04
  • Thanks. But, still, nothing changes in the error after dereferencing - the errors are exactly the same. Commented May 24, 2024 at 16:09
  • The errors cannot be exactly the same, because types change. Do note that dereferencing has lower precedence than function call operator, so it should be (*data::tbl)(4, 0). But that doesn't solve your main problem, this is no different than returning a pointer and suffers from the same problem of potentially dereferencing null. Commented May 24, 2024 at 16:13
  • 1
    Just don't do it. You are basically arguing that a reference can't be a nullptr, so you're adding all that extra work to create a reference with a bool to indicate whether it's even a valid reference. Really, if you need a "doesn't exist" result, a pointer will do just fine. Another alternative, especially if this is just meant to be an error-checking mechanic, is to return a reference or throw an error. Commented May 24, 2024 at 16:30
  • Ok, so all in all, I'm going to either stick to the pointers or rethink the whole design. But, considering that you have to dereference the return value of std::reference_wrapper>, why does it even exists? Isn't it always better (I mean, simpler - you don't need to #include <optional>) to just use pointers then? Commented May 24, 2024 at 16:31

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.