-1

I am trying to implement a wrapping function named: Shape& move_up(int index), that will access and modify1 elements of vector<T*> v, in the derived class, named: class Group.

I am trying to do that by wrapping the T& operator[](int i) { return *v[i]; } of the base class:

Group.h:

// class Group is a container of Shapes
class Group: public Graph_lib::Vector_ref<Shape>{
public:
    // constructors
    Group::Group()  
     : upperLeft(0, 0), gridSideX(50), gridSideY(50), gridRowNumber(5), gridColumnNumber(5) 
    {
     // create grid
     for (size_t i = 0; i <= gridRowNumber; ++i){ 
         for (size_t j = 0; j <= gridColumnNumber; ++j){
              Graph_lib::Rectangle* rec = new Graph_lib::Rectangle(Point(upperLeft.x + gridSideX * j, upperLeft.y + gridSideY * i), gridSideX, gridSideY);
              rec->set_fill_color(((i + j) % 2 == 0) ? Color::black : Color::white); 
              push_back(rec);
         }
     }   
    } 

    Shape& move_up(int i) { return operator[](i).move(0, 70); }
private:
    Point upperLeft;
    int gridSideX;
    int gridSideY;
    int gridRowNumber;
    int gridColumnNumber;
};

main.cpp

#include <iostream> 
#include <vector>
#include "Graph.h"
#include "Simple_window.h"
#include "Group.h"

int main(){
    // define a window 
    Point tl(x_max()/2,0);
    int width = 700;
    int height = 700;
    string label = "class Group";
    Simple_window sw(tl, width, height, label);

    // instantiate a class Group object  
    Group gr();
    for (size_t i = 0; i < gr.size(); ++i) sw.attach(gr[i]);
    sw.wait_for_button();
}

Currently the wrapping function is getting underlined in red, when hover above it displays the following message:

Error: initial value to reference to non-const must be an lvalue

The problem is that I can't find a right way of accessing and modifying the elements in the vector of the base class, thus the following question:

What am I doing wrong? How to correctly implement the Shape& move_up(int index); function?


1. Apply the function move(); that changes the coordinates of a Shape element of the vector.

2. All the additional files for compilation could be found: here and here.

Ziezi
  • 6,375
  • 3
  • 39
  • 49
  • 5
    Does this really have anything to do with overloading `operator[]`, or with inheritance, or with templates? What does `.move()` return? If it's not a reference, the return value for `move_up` cannot be bound. Present a [minimal testcase](http://stackoverflow.com/help/mcve) (and, please, I shouldn't have to prompt you to do this every time I see one of your questions) – Lightness Races in Orbit Oct 15 '15 at 10:11
  • 2
    It seems like `Group` inheriting from `MyVector` is in violation of the Liskov Substitution Principle. – TartanLlama Oct 15 '15 at 10:13
  • @TartanLlama Just read the principle; the class would probably be implemented with `MyVector` as data member. – Ziezi Oct 15 '15 at 13:20
  • 1
    @simplicisveritatis exactly. That would solve your issue as a side-effect. – TartanLlama Oct 15 '15 at 13:21

2 Answers2

2

Your function move() returns void:

virtual void move(int dx, int dy);

What do you expect then when you try to have your move_up() return the result of move():

return <something>.move(0, 70);

especially that you previously told the compiler that move_up() shall returns Shape&?

Petr
  • 9,812
  • 1
  • 28
  • 52
2

The function move_up() has to:

  • modify Shape's coordinate
  • return Shape& such that it could be attache()d to the window object, and its new location displayed on the screen.

To do that it just needs to be separated into two lines, where the first line modifies the Shape object and the second line returns it by reference:

Shape& move_up(int i) {
    operator[](i).move(0, 70); 
    return operator[](i);
}

or as suggested by molbdnilo:

Shape& move_up(int i) {
    auto& el = (*this)[i];
    el.move(0, 70); 
    return el;
}
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Ziezi
  • 6,375
  • 3
  • 39
  • 49