Перегрузка оператора <<
Пытаюсь перегрузить оператор <<, уже много туториалов посмотрел, все время выдает ошибки по типу 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 шт):
У вас в
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()) - так, детская шалость...
Оператор вывода выводит 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;
}