Issues compiling Tic Tac Toe project from Learn C++ course

Hello everyone!

Although this problem comes from a specific project, I think the question is a universal C++ compilation issue for a data type I’m trying to declare/initialize.

When compiling a file that includes this line:

std::vector<std::string> holder = {" ", " "};

using the terminal input “g++ <+ the file name>,” I get the following information:

error: non-aggregate type ‘std::vectorstd::string’ (aka ‘vector<basic_string<char, char_traits, allocator > >’) cannot be
initialized with an initializer list

When I type in “g++ --version,” it tells me “Apple clang version 12.0.0.”

Does anyone know if this has to do with the compiler or version I’m using? I can definitely provide more info if more context is needed. Thanks!
-Justin

As a follow-up, I’ve seen on some forums to include -std=c++11, but when I do that, I get a firehose of information from the terminal which I honestly cannot parse.

what’s the rest of your project look like? I can try to reproduce it locally.

It consists of three files, which I’ll add separately in the following three comments. Thanks!

filename ttt.cpp

#include <iostream>
#include "ttt_functions.hpp"

int main() {

    opening();
    play_game();

}

filename ttt_functions.hpp

#include <iostream>
#include <vector>
#include <string>

void opening();
void print_grid();
void update_grid(std::string player_move);
void check_for_winner();
int end_game();
void play_game();

filename ttt_functions.cpp

#include <iostream>
#include <vector>
#include <string>
#include "ttt_functions.hpp"

// VARIABLES AND CONSTANTS

std::vector<std::string> gridHeader = {" ", "1", " ", " ", " ", "2", " ", " ", " ", "3"};
std::vector<std::string> gridRow1 = {"A", " ", " ", "|", " ", " ", " ", "|", " ", " "};
std::vector<std::string> gridRow2 = {" ", "_", " ", " ", " ", "_", " ", " ", " ", "_"};
std::vector<std::string> gridRow3 = {"B", " ", " ", "|", " ", " ", " ", "|", " ", " "};
std::vector<std::string> gridRow4 = {" ", "_", " ", " ", " ", "_", " ", " ", " ", "_"};
std::vector<std::string> gridRow5 = {"C", " ", " ", "|", " ", " ", " ", "|", " ", " "};
std::vector<std::string> moves = {"1A", "1B", "1C", "2A", "2B", "2C", "3A", "3B", "3C"};
std::vector<std::string> remaining_moves = {"1A", "1B", "1C", "2A", "2B", "2C", "3A", "3B", "3C"};
std::string player1;
std::string player2;
std::string player = player1;
char player1_symbol;
char player2_symbol;
char player_symbol = player1_symbol;
int turn = 0;
std::string winner;
std::string next_move;

void opening() {
    std::cout << "Player 1, please enter your name: ";
    std::cin >> player1;
    std::cout << "Player 1, please enter your player symbol: ";
    std::cin >> player1_symbol;
    std::cout << "Player 2, please enter your name: ";
    std::cin >> player2;
    std::cout << "Player 2, please enter your player symbol: ";
    std::cin >> player2_symbol;
}

void print_grid() {
    std::cout << gridHeader << "\n";
    std::cout << gridRow1 << "\n";
    std::cout << gridRow2 << "\n";
    std::cout << gridRow3 << "\n";
    std::cout << gridRow4 << "\n";
    std::cout << gridRow5 << "\n";
}

void update_grid(std::string player_move) {
    switch (player_move) {
        case "1A":
            gridRow1[1] = player_symbol;
            break;
        case "1B":
            gridRow3[1] = player_symbol;
            break;
        case "1C":
            gridRow5[1] = player_symbol;
            break;
        case "2A":
            gridRow1[5] = player_symbol;
            break;
        case "2B":
            gridRow3[5] = player_symbol;
            break;
        case "2C":
            gridRow5[5] = player_symbol;
            break;
        case "3A":
            gridRow1[9] = player_symbol;
            break;
        case "3B":
            gridRow3[9] = player_symbol;
            break;
        case "3C":
            gridRow5[9] = player_symbol;
            break;
        default:
            break;
    }
}

void check_for_winner() {
    if (
        moves[0] == player1_symbol && moves[1] == player1_symbol && moves[2] == player1_symbol ||
        moves[3] == player1_symbol && moves[4] == player1_symbol && moves[5] == player1_symbol ||
        moves[6] == player1_symbol && moves[7] == player1_symbol && moves[8] == player1_symbol ||
        moves[0] == player1_symbol && moves[3] == player1_symbol && moves[6] == player1_symbol ||
        moves[1] == player1_symbol && moves[4] == player1_symbol && moves[7] == player1_symbol ||
        moves[2] == player1_symbol && moves[5] == player1_symbol && moves[8] == player1_symbol ||
        moves[0] == player1_symbol && moves[4] == player1_symbol && moves[8] == player1_symbol ||
        moves[2] == player1_symbol && moves[4] == player1_symbol && moves[6] == player1_symbol ||
        ) {
            winner = player1;
    } else if (
        moves[0] == player2_symbol && moves[1] == player2_symbol && moves[2] == player2_symbol ||
        moves[3] == player2_symbol && moves[4] == player2_symbol && moves[5] == player2_symbol ||
        moves[6] == player2_symbol && moves[7] == player2_symbol && moves[8] == player2_symbol ||
        moves[0] == player2_symbol && moves[3] == player2_symbol && moves[6] == player2_symbol ||
        moves[1] == player2_symbol && moves[4] == player2_symbol && moves[7] == player2_symbol ||
        moves[2] == player2_symbol && moves[5] == player2_symbol && moves[8] == player2_symbol ||
        moves[0] == player2_symbol && moves[4] == player2_symbol && moves[8] == player2_symbol ||
        moves[2] == player2_symbol && moves[4] == player2_symbol && moves[6] == player2_symbol
        ) {
            winner = player2;
    } else {
        std::cout << "Your turn is ended.";
    }
}  

int end_game() {
    std::cout << winner << " has won the game!";
    return 0;
}

void play_game() {
    while (winner != player1 || winner != player2) {
        std::cout << player << ", it is your turn";
        std::cout << "Please enter your next move from the remaining spaces: ";
        for (int i = 0; i < remaining_moves.size(); i++) {
            std::cout << remaining_moves[i];
        }
        print_grid();
        std::cin >> next_move;
        bool checker = false;
        while (checker == false) {
            for (int i = 0; i < remaining_moves.size(); i++) {
                if (remaining_moves[i] == next_move) {
                    checker == true;
                    break;
                }
            }
            std::cout << "That entry was incorrect. Please re-enter your next move.";
            std::cin >> next_move;
        }
        checker = false;
        
        for (int i = 0; i < moves.size(); i++) {
            if (moves[i] == next_move) {
                moves[i] = player_symbol;
            }
        }
        for (int i = 0; i < remaining_moves.size(); i++) {
            if (remaining_moves[i] == next_move) {
                for (int j = i; j < remaining_moves.size(); j++) {
                    remaining_moves[j] = remaining_moves[j+1];
                    break;
                }
            }
        }

        if (turn % 2 == 1) {
            player = player1;
            player_symbol = player1_symbol;
        } else {
            player = player2;
            player_symbol = player2_symbol;
        }
        turn++;

        update_grid(next_move);
        check_for_winner();
        
        if (winner == player1 || winner == player2) {
            end_game();
        }
    }
}


(It’s a tic tac toe game, FYI)

If I understand your problem, it stems from compiling this type of code:

#include <iostream>
#include <vector>
#include <string>

int main() {
	std::vector<std::string> moves = {"1A", "1B", "1C", "2A", "2B", "2C", "3A", "3B", "3C"};
    return 0;
}

Which needs to compile on C++11 or higher.

I’m on mac and both of these work for me:
g++ -std=c++11 -o test test.cpp
or
clang++ -std=c++11 -o test test.cpp

Additionally, I’m always reticent about running a lot of code on top of things I’m not sure can compile. Although if I’m studying someone else’s code, I’ll try to isolate it in a controlled environment just to make sure there’s no chance of anything else interfering with what’s happening.

Adding this for testing

for (auto i=0; i!=9; ++i){
		std::cout << moves[i];
		std::cout << "\n";
	}

produces the desired output:

1A
1B
1C
2A
2B
2C
3A
3B
3C

Thanks, toastedpitabread.

When I compile the code you have provided, I also do not get errors. Do you know why I am getting the error message

error: non-aggregate type ‘std::vectorstd::string’ (aka ‘vector<basic_string<char, char_traits, allocator > >’) cannot be
initialized with an initializer list

on my original files? I compiled with -std=c++11 as before.

When I isolate the string vectors, they compile. When I include the rest of my code, it has an issue with the string vectors specifically and throws errors up top, where they are declared.

Thanks again!
-Justin

I would try rebuilding that code from the bottom up to isolate what is wrong, it’s a good debugging exercise.

@friskybunnies1 for example, if I comment out everything but opening() in the files, it still compiles fine for me. Which makes me think the compiling issue is not in opening(). Not necessarily in play_game(), but not in opening().

int main() {

    opening();
    //play_game();

} 

(I compiled thus: g++ -std=c++11 -o test ttt.cpp ttt_functions.cpp)

But part of the art of it all is the problem-solving bit. You have a chance to isolate it further so I’ll leave it to you, you’re close to this one issue… it may uncover many others though (but don’t lose spirit!)

The syntax of = {} is why you have this error
{} is an initializer list it initializes the data structure with whats in the brackets. if you say = brackets you are trying to assign your vector to an initializer list instead of using that initializer list on the vector

You can use the ={} syntax in c++11 or greater but it isn’t advised
Try to use {} when initializing anything in modern cpp
Using = is ok too, but = {} is usually trouble

2 Likes

Awesome; thanks so much for your help! :slight_smile:
You’re right, I’ve already gotten a little further past that issue. I’ll keep tinkering. Thanks again!

-Justin