Roozbeh
Roozbeh

Reputation: 77

Creating [][] operator for class in c++

I am making a Pentago game for someone, and I wanted to write a good code, so I decided to use operator overloading.

We have 2 classes; first one is Block class (which represents every single block of the board) and the second one is Set class (which represents a 3*3 table of blocks). Now I want to use Set as a 2d array so I can use set[foo][foo]. Can you help me to make an operator like this?

Upvotes: 4

Views: 335

Answers (5)

OMGtechy
OMGtechy

Reputation: 8220

Assuming the memory is contiguous, you can return a pointer to the first element of the row.

Working example

#include <iostream>

class MyType
{
public:
    static const size_t rows = 3;
    static const size_t columns = 3;
    static const size_t size = rows * columns;

    MyType()
    {
        for(size_t index = 0; index < 9; ++index)
        {
            data[index] = index;
        }
    }

    int* operator[](size_t index)
    {
        return &data[rows * index];
    }

private:
    int data[size];
};

int main()
{
    MyType instance;

    std::cout << instance[2][1] << std::endl;
}

Upvotes: 0

Ami Tavory
Ami Tavory

Reputation: 76297

There are (at least) two ways to go here.


The first is to make something like a set_row class, which is a proxy. So you'd have something like

class set
{
public:
    set_row operator[](size_t row)
    {
        // Return a proxy object that just sees the correct row.
        return set_row(internal_buffer_pointer[row]);
    }

    ...
};

where set_row is something like

class set_row
{
public:
     // Ctor takes a row

     // Take a column, and return a reference to the correct column in the row.
     element &operator[](size_t column);
};

From experience (on, ahem, VisualC++), this was slow, as it will need to construct a proxy object for each access.


The second is to forgo operator[], and use operator():

class set
{
public:
    element &operator()(size_t row, size_t col);


    ...
};

It would be nice using operator[], but, unfortunately, you can't do that with it.

Upvotes: 3

Galik
Galik

Reputation: 48615

There is no operator[][]. If you want to provide those semantics you need to overload operator[] such that it returns another object that also overloads operator[].

Your case can be solved using a vector of vectors:

#include <vector>
#include <cstdint>
#include <iostream>

struct Block
{
    int value = 0;
};

class Set
{
    std::vector<std::vector<Block> > grid;

public:
    Set(): grid(3, std::vector<Block>(3)) {} // 3 x 3

    std::vector<Block>& operator[](std::size_t x) { return grid[x]; }
};

int main()
{
    using std::size_t;

    Set set;

    set[1][1].value = 1;

    for(size_t x = 0; x < 3; ++x)
    {
        for(size_t y = 0; y < 3; ++y)
        {
            std::cout << set[x][y].value << ' ';
        }
        std::cout << '\n';
    }
}

Output:

0 0 0 
0 1 0 
0 0 0 

This works because Set::operator[] returns reference to a std::vector and the std::vector overloads operator[] to return a reference to a Block.

Upvotes: 1

6502
6502

Reputation: 114481

A very simple solution is

struct MyClass {
    int x[3][3];
    int* operator[](int row) { return &(x[row][0]); }
};

i.e. returning an element* from operator[].

This allows using

myinstance[row][col]

Upvotes: 3

Peter
Peter

Reputation: 36597

There is no way to supply an operator[][] for a class.

However, if your Set supplies an operator[](), that operator can return a reference to something else that also has an operator[]().

For example;

 class Row
 {
      public:

           Block &operator[](int block_no) {return data[block_no];};

      private:

           std::vector<Block> data;
 };

 class Set
 {
       public:

          Row &operator[](int row_no) {return row[row_no];};

       private:
           std::vector<Row> row;
 };

 int main()
 {
     Set s;
       // assume s is set up appropriately
     Block b = s[2][3];    //  equivalent to s.operator[](2).operator[](3)
 }

Obviously, it is also necessary to do relevant error checking, set up the contents of the classes correctly, etc.

Upvotes: 1

Related Questions