0

I have the following code: I want to access my occupancy grid outside function to pass a test case:

struct Indices
{
  int x;
  int y;
  
  Indices(const Indices&) = default;
  Indices(const int _x = 0, const int _y = 0) : x{_x}, y{_y} {}
};

/// Addition operator overload between two Indices
static inline Indices operator+(const Indices lhs, const Indices rhs)
{
  return Indices{lhs.x + rhs.x, lhs.y + rhs.y};
}

/// Equality operator overload between two Indices
static inline bool operator==(const Indices lhs, const Indices rhs)
{
  return lhs.x == rhs.x and lhs.y == rhs.y;
}

Occupancy class:

class OccupancyGrid
{
public:
  using occupancy_t = uint8_t;

  static constexpr occupancy_t FREE = 0;
  static constexpr occupancy_t OCCUPIED = 1;
  
  std::vector<std::vector<occupancy_t>>occ_map;

  /**
   *  Initializes the (fixed) size of the grid and initial value for all cells
   */
  explicit OccupancyGrid(const Indices size, const occupancy_t initial_value = FREE){
    /// TO BE IMPLEMENTED
    size_= size;
    data_= new occupancy_t(initial_value);
    occ_map.resize(size.x,std::vector<occupancy_t>(size.y,initial_value));
  }  
     
  /// Destructor
  ~OccupancyGrid()
  { 
    delete data_;
  }

  /**
   *  Returns the occupancy value for a cell located at `idx = (x, y)`
   */
  occupancy_t operator[](const Indices& idx) const
  {
    /// TO BE IMPLEMENTED    
    return occ_map[idx.x][idx.y];    
  }
    
  /**
   *  Returns the size of the grid
   */
  Indices size() const
  {
    return size_;
  }

private:
  /// Size of the grid (size_.x := # of rows, size_.y := # of cols)
  Indices size_;
  /// Pointer to memory allocated to hold grid cell values
  occupancy_t* data_;  
};

The Test case:

TEST_CASE( "OccupancyGrid::operator[]" ) {

  OccupancyGrid grid{Indices{100, 50}, OccupancyGrid::FREE};

  grid[Indices{50, 49}] = OccupancyGrid::OCCUPIED;

  REQUIRE( grid[Indices{48, 48}] == OccupancyGrid::FREE);  
  REQUIRE( grid[Indices{50, 49}] == OccupancyGrid::OCCUPIED);
}

Note: Please focus on "TO BE IMPLEMENTED" part.

I was provided the test case as follows hence I have created a 2d vector grid and filled the grid with "FREE" during the constructor initialization. When the "[]" operator is called in test case, the grid cell status at that index should change.

Hence, I have returned the occ_map value to [] operator overload function it says:

error: lvalue required as left operand of assignment
   grid[Indices{50, 49}] = OccupancyGrid::OCCUPIED;   

for the test case:

grid[Indices{50, 49}] = OccupancyGrid::OCCUPIED;

but passes the assertion for this:

REQUIRE( grid[Indices{48, 48}] == OccupancyGrid::FREE);  

Can anyone please tell me how to solve this and what should I do to complete the [] operator overload function?

Kiran Sai
  • 1
  • 1

1 Answers1

1

Tl;DR version

Add

occupancy_t & operator[](const Indices& idx)
{
    return occ_map[idx.x][idx.y];    
}

to the OccupancyGrid class definition.

Explanation

occupancy_t operator[](const Indices& idx) const 

defines a function that cannot be used to modify the object on which it is invoked, making

grid[Indices{50, 49}] = OccupancyGrid::OCCUPIED;

problematic.

You want to keep this version of the operator around for use with const objects, so you want to add another version of the operator that looks more like

occupancy_t & operator[](const Indices& idx)

This one is not a constant method, so it can modify the object, and also returns a reference to the element inside the OccupancyGrid's backing array which can be directly updated. This makes

grid[Indices{50, 49}] = OccupancyGrid::OCCUPIED;

viable.

Side Notes

OccupancyGrid does not observe the Rule of Three. A copy, accidental or otherwise, will be fatal. Whatever is being deleted in the destructor will wreck havoc if it is not correctly copied from one instance to another.

Here is a link to a better way to write OccupancyGrid that addresses the problem with direct assignments and eliminates the need for the Indices class.

user4581301
  • 33,082
  • 7
  • 33
  • 54
  • Hi @user458, thank you for your answer but I have also tried the other function. It shows the error. But, the test function provided as follows and I cant change it. Do you think create a global or static vector might help? – Kiran Sai Sep 20 '21 at 17:44
  • @ user If possible can you please contact me through my email? My email address is available on my profile. I like to share the file content to explain easier what I was talking about. – Kiran Sai Sep 20 '21 at 17:52
  • @KiranSai Updated question to make what you need to do more explicit. You are stuck with the `Indices` class because it's part of the API. The point of the side notes is it demonstrates a more efficient way to get the same behaviour. – user4581301 Sep 20 '21 at 18:33