Previous question:

https://codereview.stackexchange.com/questions/70650/tic-tac-toe-in-c11-follow-up

Is there any way to improve this code?

    #include <iostream>
    #include <cctype>
    #include <algorithm>
    #include <functional>
    #include <array>
    
    enum struct Player : char
    {
    	none	= '-',
    	first	= 'X',
    	second	= 'O'
    };
    
    std::ostream& operator<<(std::ostream& os, Player p)
    {
    	return os << static_cast<char>(p);
    }
    
    enum struct Type : int
    {
    	row = 0,
    	column = 1,
    	diagonal = 2
    };
    
    enum struct Lines : int
    {
    	first	= 0,
    	second	= 1,
    	third	= 2
    };
    
    class TicTacToe
    {
    public:
    	TicTacToe(); 
    	bool isFull() const;
    	void draw() const;
    	void turn(Player player);
    	bool check(Player player) const;
    
    private:
    	bool applyMove(Player player, int position);
    
    	static const std::size_t mDim = 3;
    	std::array<Player, mDim * mDim> mGrid;
    };
    
    // utility functor to compute matching condition
    template<int dim>
    struct Match 
    {
    	Match(Type t, Lines i) : mCategory(t), mNumber(i){}
    	bool operator() (int number) const
    	{
    		switch (mCategory)
    		{
    		case Type::row:
    			return (std::abs(number / dim) == static_cast<int>(mNumber));
    		case Type::column:
    			return (number % dim == static_cast<int>(mNumber));
    		case Type::diagonal:
    			if (mNumber == Lines::first)
    				return ((std::abs(number / dim) - number % dim) == static_cast<int>(mNumber));
    			else
    				return ((std::abs(number / dim) + number % dim) == static_cast<int>(mNumber));
    		}
    		
    		return false; 
    	}
    	Type mCategory;
    	Lines mNumber;
    };
    
    TicTacToe::TicTacToe() 
    { 
    	mGrid.fill(Player::none);
    }
    
    bool TicTacToe::applyMove(Player player, int position)
    {
    	if (mGrid[position] != Player::none)
    		return false;
    	mGrid[position] = player;
    	return true;
    }
    
    bool TicTacToe::isFull() const
    {
    	return 0 == std::count_if(mGrid.begin(), mGrid.end(),
    		[](Player i)
    	{
    		return i == Player::none;
    	});
    }
    
    bool TicTacToe::check(Player player) const
    {
    	// check for row or column wins
    	std::array<bool, 8> win;
    	win.fill(true);
    
    	int j = 0;
    
    	// checking condition loop
    	std::for_each(mGrid.begin(), mGrid.end(),
    		[&](Player i)
    	{
    		int x = j++;
    
    		// columns
    		if (Match<mDim>(Type::column, Lines::first)(x))
    			win[0] &= i == player;;
    		if (Match<mDim>(Type::column, Lines::second)(x))
    			win[1] &= i == player;
    		if (Match<mDim>(Type::column, Lines::third)(x)) 
    			win[2] &= i == player;
    
    		// rows
    		if (Match<mDim>(Type::row, Lines::first)(x))
    			win[3] &= i == player;
    		if (Match<mDim>(Type::row, Lines::second)(x))
    			win[4] &= i == player;
    		if (Match<mDim>(Type::row, Lines::third)(x))
    			win[5] &= i == player;
    
    		// diagonals
    		if (Match<mDim>(Type::diagonal, Lines::first)(x))
    			win[6] &= i == player;
    		if (Match<mDim>(Type::diagonal, Lines::third)(x))
    			win[7] &= i == player;
    	});
    
    	for (auto i : win)
    	{
    		if (i)
    			return true;
    	}
    
    	return false;
    }
    
    void TicTacToe::draw() const
    {
    	//Creating a onscreen grid
    	std::cout << ' ';
    	for (auto i = 1; i <= mDim; ++i)
    		std::cout << "  " << i;
    
    	int j = 0;
    	char A = 'A';
    
    	for (auto i : mGrid)
    	{
    		if (Match<mDim>(Type::column, Lines::first)(j++))
    			std::cout << "\n " << A++;
    
    		std::cout << ' ' << i << ' ';
    	}
    
    	std::cout << "\n\n";
    }
    
    void TicTacToe::turn(Player player)
    {
    	char row = 0;
    	char column = 0;
    	std::size_t position = 0;
    	bool applied = false;
    
    	std::cout << "\n" << player << ": Please play. \n";
    
    	while (!applied)
    	{
    		std::cout << "Row(1,2,3,...): ";
    		std::cin >> row;
    		std::cout << player << ": Column(A,B,C,...): ";
    		std::cin >> column;
    
    		position = mDim * (std::toupper(column) - 'A') + (row - '1');
    
    		if (position < mGrid.size())
    		{
    			applied = applyMove(player, position);
    
    			if (!applied)
    				std::cout << "Already Used. Try Again. \n";
    		}
    		else
    		{
    			std::cout << "Invalid position.  Try again.\n";
    		}
    	}
    
    	std::cout << "\n\n";
    }
    
    class Game
    {
    public:
    	Game() = default;
    	void run();
    
    private:
    	TicTacToe mTicTacToe;
    	std::array<Player, 2> mPlayers{ { Player::first, Player::second } };
    	int mPlayer = 1;
    
    	void resultScreen(bool winner);
    	std::function<void()>		display = std::bind(&TicTacToe::draw, &mTicTacToe);
    	std::function<void(Player)>	turn	= std::bind(&TicTacToe::turn, &mTicTacToe, std::placeholders::_1);
    	std::function<bool(Player)>	win		= std::bind(&TicTacToe::check, &mTicTacToe, std::placeholders::_1);
    	std::function<bool()>       full	= std::bind(&TicTacToe::isFull, &mTicTacToe);
    };
    
    void Game::run()
    {
    	while (!win(mPlayers[mPlayer]) && !full())
    	{
    		mPlayer ^= 1;
    		display();
    		turn(mPlayers[mPlayer]);
    	}
    
    	resultScreen(win(mPlayers[mPlayer]));
    }
    
    void Game::resultScreen(bool winner)
    {
    	display();
    
    	if (winner)
    	{
    		std::cout << "\n" << mPlayers[mPlayer] << " is the Winner!\n";
    	}
    	else
    	{
    		std::cout << "\nTie game!\n";
    	}
    }
    
    int main()
    {
    	Game game;
    	game.run();
    }