Reputation: 113
I am trying to create a network of a custom class Tile
inside another class Board
which is storing a std::array<std::shared_ptr<Tile>, 34>
. I am using std::shared_ptr<Tile>
objects within class Tile
to show which nodes are connected. However, when I initialise each of the 34 Tile
objects, the not yet initialised objects included in the list do not get updated from nullptr
to their own reference.
#include <memory>
#include <array>
#include <cstddef>
struct Tile;
template <const std::size_t N> using TileLink = std::array<const std::shared_ptr<const Tile>, N>;
template <const std::size_t N> using TileArray = std::array<std::shared_ptr<const Tile>, N>;
struct Tile {
/* surrounding tiles */
const std::size_t ID;
const std::size_t num_adj;
const TileLink<6> adjacent;
Tile (std::size_t id, std::size_t n, const TileLink<6> & arr) : ID (id), num_adj (n), adjacent (arr) { }
~Tile (void) = default;
};
class Board {
private:
TileArray<34> tiles;
public:
Board (void);
~Board (void) = default;
};
Board :: Board (void) {
/* Column 1 */
tiles[0] = std::make_shared<Tile> ( 0, 3, TileLink<6>{ tiles[1], tiles[4], tiles[5], nullptr, nullptr, nullptr });
tiles[1] = std::make_shared<Tile> ( 1, 4, TileLink<6>{ tiles[0], tiles[2], tiles[5], tiles[6], nullptr, nullptr });
tiles[2] = std::make_shared<Tile> ( 2, 3, TileLink<6>{ tiles[1], tiles[6], tiles[7], nullptr, nullptr, nullptr });
/* Column 2 */
tiles[3] = std::make_shared<Tile> ( 3, 2, TileLink<6>{ tiles[4], tiles[9], nullptr, nullptr, nullptr, nullptr });
tiles[4] = std::make_shared<Tile> ( 4, 5, TileLink<6>{ tiles[0], tiles[3], tiles[5], tiles[9], tiles[10], nullptr });
tiles[5] = std::make_shared<Tile> ( 5, 6, TileLink<6>{ tiles[0], tiles[1], tiles[4], tiles[6], tiles[10], tiles[11] });
tiles[6] = std::make_shared<Tile> ( 6, 6, TileLink<6>{ tiles[1], tiles[2], tiles[5], tiles[7], tiles[11], tiles[12] });
tiles[7] = std::make_shared<Tile> ( 7, 5, TileLink<6>{ tiles[2], tiles[6], tiles[8], tiles[12], tiles[13], nullptr });
tiles[8] = std::make_shared<Tile> ( 8, 2, TileLink<6>{ tiles[7], tiles[13], nullptr, nullptr, nullptr, nullptr });
/* Columns 4 - 6 */
...
...
...
/* Column 7 */
tiles[31] = std::make_shared<Tile> (31, 3, TileLink<6>{ tiles[26], tiles[27], tiles[32], nullptr, nullptr, nullptr });
tiles[32] = std::make_shared<Tile> (32, 4, TileLink<6>{ tiles[27], tiles[28], tiles[31], tiles[33], nullptr, nullptr });
tiles[33] = std::make_shared<Tile> (33, 3, TileLink<6>{ tiles[28], tiles[29], tiles[32], nullptr, nullptr, nullptr });
}
The std::array
I am passing to the Tile
constructor does not change. How would I get it to change?
Any help would be greatly appreciated. Sorry for making the question so long, I didn't really know how to make this a smaller example.
Upvotes: 0
Views: 129
Reputation: 113
I have solved my problem - thanks to @t.niese and @fjardon for your help.
I had to make Tile
more complex to facilitate the real issue here: that I was unable to create a unique Tile
object from std::array in the class. So I added a copy constructor and an assignment operator, removed the smart pointers and the const
-ness and made the array of class type Tile
.
class Tile;
template <const std::size_t N> using TileLink = std::array<const Tile *, N>;
template <const std::size_t N> using TileArray = std::array<Tile, N>;
enum class OWNERSHIP { PLAYER_1, PLAYER_2, CONTESTED };
class Tile {
private:
OWNERSHIP territory;
/* surrounding tiles */
std::size_t ID;
std::size_t num_adj;
TileLink<6> adjacent = { nullptr };
public:
Tile (void) { }
Tile (OWNERSHIP own, std::size_t id, std::size_t num, const TileLink<6> & arr);
Tile (const Tile & rhs);
Tile & operator = (Tile other);
~Tile (void) = default;
};
class Board {
private:
TileArray<34> tiles;
void create_col_1_and_7 (void);
void create_col_2 (void);
...
void create_col_6 (void);
public:
Board (void);
~Board (void) = default;
};
Each of the initialisation now looks like:
tiles[0] = Tile (OWNERSHIP::PLAYER_2, 0, 3, TileLink<6>{ &tiles[1], &tiles[4], &tiles[5], nullptr, nullptr, nullptr });
tiles[1] = Tile (OWNERSHIP::CONTESTED, 1, 4, TileLink<6>{ &tiles[0], &tiles[2], &tiles[5], &tiles[6], nullptr, nullptr });
...
tiles[32] = Tile (OWNERSHIP::CONTESTED, 32, 4, TileLink<6>{ &tiles[27], &tiles[28], &tiles[31], &tiles[33], nullptr, nullptr });
tiles[33] = Tile (OWNERSHIP::PLAYER_1, 33, 3, TileLink<6>{ &tiles[28], &tiles[29], &tiles[32], nullptr, nullptr, nullptr });
Upvotes: 0
Reputation: 7996
Here:
tiles[0] = std::make_shared<Tile> ( 0, 3, TileLink<6>{ tiles[1], tiles[4], tiles[5], nullptr, nullptr, nullptr });
tiles[1]
, tiles[4]
, and so on, are not yet initialized and are shared_ptr
to nullptr. When you initialize tiles[1]
later it doesn't change what is inside tiles[0]
.
You are completely misusing shared_ptr
. Since your tile array has a fixed size, just allocate once all the needed memory and then use non-owning pointers. Because there is a owner for the memory and it is Board
.
Upvotes: 2