Перегрузка оператора <<

Пытаюсь перегрузить оператор <<, уже много туториалов посмотрел, все время выдает ошибки по типу passing 'const Lexer' as 'this' argument of 'std::map<int, std::basic_string<char> > Lexer::read_file()' discards qualifiers [-fpermissive], no match for 'operator<<' in 'stream << Lexer::read_file()()', no match for 'operator<<' in 'std::cout << outtokens'. Код:

#include <iostream>
#include <fstream>
#include <map>
#include <ostream>
using std::map;

class Lexer {
    public:
        map <int, std::string> tokens;
        std::string content;
        std::ifstream file;
        int line = 1;
        ~Lexer() {
            file.close();
        }
        map <int, std::string> read_file() {
            file.open("code.kspl");
            if (!file) {
                std::cout << "Cannot open file" << std::endl;
            }
            else {
                while (!file.eof()) {
                    getline(file, content);
                    if (content.find("out") == 0) {
                        content.erase(0, 5);
                        content.erase(content.length()-1, 1);
                        tokens[line] = "PRINT " + content;
                    }
                    line+=1;
                    //std::cout << content << std::endl;
                }
                return tokens;
            }
        }
};

class Parser {
    public:
        map <std::string, int> intvars;
        map <std::string, float> floatvars;
        map <std::string, std::string> strvars;
        map <std::string, bool> boolvars;
        bool isError = false;
        ~Parser() {
            if (isError) {
                std::cout << "[Program finished with error]";
            }
            else {
                std::cout << "[Program finished with exit status OK]";
            }
        }
};

std::ostream& operator<<(std::ostream& stream, const Lexer& lexer) {
    stream << lexer.read_file();
    return stream;
}

int main() {
    Lexer lexer;
    map <int, std::string> outtokens = lexer.read_file();
    std::cout << outtokens << std::endl;
    return 0;
}

Как исправить?


Ответы (2 шт):

Автор решения: Harry

У вас в

stream << lexer.read_file();

что выводится?

Вот такой map:

map <int, std::string> read_file();

Скажите, а что, уже есть стандартный оператор << для вывода map? Нет. Так что это не сработает в любом случае. Ваша же ошибка - вы передаете в оператор константную ссылку

std::ostream& operator<<(std::ostream& stream, const Lexer& lexer) {

а функция

map <int, std::string> read_file()

неконстантная, т.е. объявленная, как изменяющая объект, для которого вызывается! И что компилятору делать? При этом вы объект реально меняете... Так что остается только писать

std::ostream& operator<<(std::ostream& stream, Lexer& lexer) {

Впрочем, как я уже говорил - работать это все равно не будет.

Да и что за странная идея - в операторе вывода заниматься чтением объекта из файла? Еще и с ветвью, которая ничего не возвращает - из функции, объявленной как возвращающая map. На этом фоне использование while (!file.eof()) - так, детская шалость...

→ Ссылка
Автор решения: KoVadim

Оператор вывода выводит map, а не Lexer. Поправим его

std::ostream& operator<<(std::ostream& stream, const map <int, std::string>& data) {
    stream << "[\n";
    for (const auto& v : data) {
        stream << "\t{" << v.first << ", " << v.second << "}\n";
    }
    stream << ']';
    return stream;
}

Если вывод не нравится - можно всегда поправить под себя.

Если не повезло и компилятор без поддержки с++11, тогда где то так

std::ostream& operator<<(std::ostream& stream, const map <int, std::string>& data) {
    stream << "[\n";
    for (const std::pair<int, std::string>& v : data) {
        stream << "t{" << v.first << ", " << v.second << "}\n";
    }
    stream << ']';
    return stream;
}
→ Ссылка