You would want to create special cases that target only the boundary cells. Then depending on each gameboard boundary in question you could perform the correct checks to see if neighbors on an opposite boundary are alive or dead to determine the next generation.
For a start, you'd have to consider the different boundaries' locations in your grid. Off the top of my head, there'd at least be cases for the leftmost column of the grid (but not counting the top or bottom cells) the rightmost column of the grid (also excluding the top and bottom cells), and same for top and bottom rows of the grid (excluding leftmost and rightmost cells in those two cases). There would then be a case individually for each corner of your gameboard/grid. It makes for some thinking and overhead initially (being that this makes 8 specialty cases in addition to your ordinary generation process), but in the end is well worth both the learning experience and the results.
Since you're using a 2-D grid, this is going to be easier than a single indexed array/vector or 1-D implementation (which still isn't that difficult when you understand the concept).
**Note: If you don't want unnecessary information that is not directly related to the implementation of your program, skip this next bit of text. If you'd like to hear more about this concept in a broad (and most likely confusing) context, read on!:
A 1-D gameboard seems odd at first, but think of it this way:
Say the user specifies the gameboard dimension size, and this value is n. Keeping it simple with a square gameboard (instead of variable length and width sizes), the entire number of cells is then n * n = N, which is what you have in a 2-D array implementation of [n][n], where both number of columns is n, and number of rows is n. For the sake of fun, I'll add just a little more for a 1-D grid implementation. The 1-D grid is represented by a singly-indexed array/vector of max index size N. You can see that it is confusing at first, but manipulating n as the index can get you to different rows, columns, etc. Using N-1, you can start at the end
of the array. Subtracting each subsequent multiple of n from N puts you at each 'row' up from the bottom, and the same works adding multiples of n from index 0 (or the beginning of the grid, (0,0) for you, upper left corner).
// end of confusing bit
Now to the point at which I said
|But for you it may just have to be a clever use of index math|
and for your case my statement was wrong. You don't need to use clever index math at all because you are using a 2-D grid. Hooray!
is your max index size for a row or column:
You should be able to access the beginning of each row (thus the left side of the grid) by:
The end of each row would then be:
Hope this helps.