2

UPDATE: Most of my relevant source code is in this pastebin: http://pastebin.com/nhAx1jfG

Can anyone make sense of this error? I'm trying to access a 2d "Tile" array I declare in a different class in the same namespace, it's public, and I do declare an object in the main "rouge.cpp" class.

g++ -Wall -Werror -lncurses -c rouge.cpp -o rouge.o
rouge.cpp: In function ‘void update_game(Player, Map, World, bool)’:
rouge.cpp:497: error: no match for ‘operator[]’ in ‘*(world.World::tiles + ((((unsigned int)player.Player::<anonymous>.GameObject::x) + 0xffffffffffffffffffffffffffffffffu) * 16u))[player.Player::<anonymous>.GameObject::y]’
rouge.cpp:506: error: no match for ‘operator[]’ in ‘*(world.World::tiles + ((((unsigned int)player.Player::<anonymous>.GameObject::x) + 1u) * 16u))[player.Player::<anonymous>.GameObject::y]’
rouge.cpp:515: error: no match for ‘operator[]’ in ‘*(world.World::tiles + ((unsigned int)(((unsigned int)player.Player::<anonymous>.GameObject::x) * 16u)))[(player.Player::<anonymous>.GameObject::y + -0x00000000000000001)]’
rouge.cpp:524: error: no match for ‘operator[]’ in ‘*(world.World::tiles + ((unsigned int)(((unsigned int)player.Player::<anonymous>.GameObject::x) * 16u)))[(player.Player::<anonymous>.GameObject::y + 1)]’
rouge.cpp:540: error: no match for ‘operator[]’ in ‘*(world.World::tiles + ((unsigned int)(((unsigned int)player.Player::<anonymous>.GameObject::x) * 16u)))[player.Player::<anonymous>.GameObject::y]’
make: *** [rouge.o] Error 1

world.h:

// The "world" class, generates a world.
class World
{
    // Public classes and variables
    public:
        // Tile array
        Tile* tiles;
        int plates[WORLDSIZEX][WORLDSIZEY];
        //Tile tiles[WORLDSIZEX][WORLDSIZEY];
        //Tile (*tiles)[WORLDSIZEX] = new Tile[WORLDSIZEX][WORLDSIZEY];
        // For plates
        //int plates[WORLDSIZEX][WORLDSIZEY];
        //plates = new int[WORLDSIZEX][WORLDSIZEY];
        //int (*plates)[WORLDSIZEX] = new int[WORLDSIZEX][WORLDSIZEY];
        // Small world
        Tile smalltiles[SMALLWORLDX][SMALLWORLDY];
        // For world temp
        int worldtemp;
        // Constructor
        World();
        void generate_plates();
        bool check_plates();
        int build_mountains(int,int);
        void add_mountains();
        void generate_world();
        void shrink_world();
        void save_world();
        void erupt();
        bool get_passable(int,int);
        char get_icon(int,int);
        char get_small_icon(int,int);
        int get_color(int,int);
        int get_small_color(int,int);
};

world.cpp where I allocate the array:

// Constructor
World::World()
{
    // Seed for random number
    srand( time(NULL) );
    tiles = new Tile[WORLDSIZEX][WORLDSIZEY];
    // Generate a world
    generate_world();
    // Shrink world
    shrink_world();
    // Then save it.
    //save_world();
}

in rouge.cpp, I access it just like:

world.tiles[i][j]; //i and j are ints in a nested for loop

after I declare it like:

World world;

and it's spitting out that error

6
  • 2
    The error doesn't mean much without the code that causes it. Commented Apr 15, 2011 at 0:04
  • Yes, you should edit your post, and see some code there Commented Apr 15, 2011 at 0:10
  • there is a lot of code... but okay. Commented Apr 15, 2011 at 0:10
  • 3
    0xffffffffffffffffffffffffffffffffu : The compiler is clearly quite enraged about something. Commented Apr 15, 2011 at 0:14
  • @Evan: Start with the line 497 + 10 lines either side. And the class definitions of any objects on line 497 Commented Apr 15, 2011 at 0:15

3 Answers 3

2

You're using a pointer to point to an array that was dynamically allocated as a multidimensional array. After the address of this multidimensional array is stored in World::tiles, the compiler "forgets" that the array was multidimensional. Thus, you can no longer use the double brackets notation (tiles[x][y]) to access an element.

To get around this, you have at least 4 options:

  1. Provide a method in World that takes x,y coordinates and returns a reference to the desired cell (you might want to provide both const and non-const versions):

    Tile& at(size_t x, size_t y) {return tiles[y*WORLDSIZEX + x];}

    const Tile& at(size_t x, size_t y) const {return tiles[y*WORLDSIZEX + x];}

  2. Roll-up your own 2D array class for World::tiles.

  3. Use a boost::multi_array for World::tiles.

  4. Declare World::tiles as vector< vector<Tile> >. The initial sizing of all nested vectors is tricky, but after that you can use the world.tiles[x][y] notation.

Plus the option @fsmc gave you.


I took a quick look at your code in the pastebin. It would be much more efficient (and cleaner looking) if you initialized your tiles vectors like this instead:

tiles.resize(WORLDSIZEX);
for(int i = 0; i < WORLDSIZEX; i++)
{
    tiles[i].resize(WORLDSIZEY);
}
Sign up to request clarification or add additional context in comments.

8 Comments

I tried #4 and still was getting bizarre errors while trying to reference. I'll replicate the error messages.
Actually, #4 works, but I'm still not able to make an array bigger than 512x512.
@Evan: Try running a stripped-down main where all you do is allocate World. See if it still crashes. If so, strip down World's constructor so that all you do is allocate your tiles. If it no longer crashes, then you might have a dangling pointer bug somewhere else that only manifests itself when World::tiles takes up a lot of memory.
@Evan: What's in a tile anyway? How much memory does each tile use up?
Small nitpick: Rogue is spelled like this: rogue. The way you spell it is for the make-up ladies put on their cheeks. :-P
|
2

world.tiles is of type Tile*. It is the wrong type to be a two dimensional array (you would need Tile**, and need to initialize it in two steps (one to create an array of Tile* pointers, and a loop to create an array that each of those Tile * pointers can point to.

e.g. in your class def:

Tile **tiles

e.g.: in your constructor:

tiles = new Tile*[SMALLWORLDX];
for (int i = 0; i < SMALLWORLDX; i++)
   tiles[i] = new Tile[SMALLWORLDY];

So getting back to what was causing your original error- when you were calling world.tiles[x][y], the first [] operator was okay, because tiles could be pointing to an array of Tiles, but the second one is not okay.

21 Comments

This is now my error: g++ -Wall -Werror -lncurses -c world.cpp -o world.o world.cpp: In constructor ‘World::World()’: world.cpp:42: error: array bound forbidden after parenthesized type-id world.cpp:42: note: try removing the parentheses around the type-id make: *** [world.o] Error 1
Sorry, there was a syntax error. You don't need the parens around new Tile*. I updated the answer.
Your problem is that you are not taking pointers when you use World as a parameter to your functions. This causes the program to create a new copy of World every time a function like draw is called. You want your functions to look like draw(World* world, etc) and when you call it, call it like draw(&myGlobalWorldObject, etc)
@Evan: You should pass World around by pointer or reference because it is very large. Passing World by value would be very inefficient. World also has pointer members, so unless you're overloading the copy constructor and assignments operators to perform a deep copy, you're going to have major dangling pointer issues. I'm going to try to find a link for you that better explains these issues.
@Evan: If world is a global object, then yes, that should work. I prefer to pass by reference whenever possible: void func(World& world) {...} invoked with func(world).
|
0

Just based on the error message, whatever you are trying to index is not actually an array. The '*' (dereference) operator at the beginning of that statement looks suspicious to me, but without actually seeing your code I can't say much else.

Comments

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.