I have a few tidbits that could help. Nothing big, but things that you can improve as you code without having to overthink them:
Use
constexpr
to represent compile-time constants.static const
works butconstexpr
pops into to head and screams "compile time!" when you read it:static constexpr std::size_t mDim = 3;
column::operator()
should beconst
-qualified since it does not alter the state ofcolumn
:bool operator() (int number) const { return (number % dim == colNum); }
unary_function
andbinary_function
are deprecated since C++11 and will be removed from the standard in C++17. Therefore, you should avoid using them. The easy fix is to defineresult_type
andargument_type
by hand (which is rahter quick) or to simply use the types at the call point where you probably know them.You could consider making the types
column
andpairCondition
immutable by making their membersconst
. Beforehand, really think about whether you want them to be immutable. It could make sense forcolumn
since functions are often immutable and this is a functor type.I don't think that you want to represent any other cells thant "no player", "player 1" and "player 2". Therefore, you could probably use an
enum struct
to represent the accepted values in your grid instead of achar
:enum struct player: char { none = '-', first = 'X', second = 'O' };
Using an
enum struct
would ensure that you don't use any other magic value and would answer the question "what does thischar
represent?" when reading the code. If you really need to access the underlying type of theenum
at different places, then use a simpleenum
instead of anenum struct
.