ostream operator overloading

I am not sure of the syntax for ostream operator overloading. My goal is for the object when printed, for File.tokens to be displayed in specific format.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <fstream>
#include <vector>

class File{
    public:
        std::vector<std::string> tokens;
    
        void write(std::string filename, std::vector<std::string> v, std::string sep="\n"){
            std::ofstream f;
            f.open(filename);
            for (std::vector<int>::size_type i = 0; i != v.size(); i++) {
                f << v[i] << sep;
            }
            f.close();
        }

        void open(std::string filename){
            std::string s = "";
            std::ifstream f;
            f.open(filename);
            while(getline(f, s)){
                this->tokens.push_back(s);
            }
            f.close();
        }
        
        //std::ostream& operator<< (std::ostream& stream, const Matrix& matrix){
        //std::string operator<<(std::string string){
        std::ostream& operator<<(std::ostream& stdout, const File& obj){
            std::string start = "[", end = "]", delim = ", ";
            std::string s;
            if (this->tokens.size() > 0){
                s += start;
                for (auto i: this->tokens){
                    s += i;
                    if (i != this->tokens.back()){
                        s += delim;
                    }
                }
                s += end;
            }
            else{
                s += start;
                s += end;
            }
            //return s;
            stdout << s;
            return stdout;
        }
};

int main(){
    File file;
    file.open("save.txt");
    std::cout << file;
    
}


The file is random data where each line is an element in the vector. For example, if save.txt was to contain:
1
2
3
4
5
test
1
2
3
4

the output of the obj would be:
[test, 1, 2, 3, 4]


the error:
1
2
3
4
5
6
7
8
9
10
11
12
test3.cpp:31:71: error: ‘std::ostream& File::operator<<(std::ostream&, const File&)’ must take exactly one argument
         std::ostream& operator<<(std::ostream& stdout, const File& obj){
                                                                       ^
test3.cpp: In function ‘int main()’:
test3.cpp:57:18: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
     std::cout << file;
                  ^
In file included from /usr/include/c++/4.8/iostream:39:0,
                 from test3.cpp:2:
/usr/include/c++/4.8/ostream:602:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = File]’
     operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
     ^
Last edited on
it has to be a friend.
they can't be member functions, since a binary operator defined as a member function must take the user-defined class (or enum) as the left argument, while I/O syntax requires std::ostream& on the left and the class on the right.
Declare them as non-member functions, outside that class body.
ah, ok thanks a lot. I did not know that.

For google searches later, here is my code fixed:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <fstream>
#include <vector>

class File{
    public:
        std::vector<std::string> tokens;
        
        friend std::ostream& operator<<(std::ostream& stdout, const File& obj);
    
        void write(std::string filename, std::string sep="\n"){
            std::ofstream f;
            f.open(filename);
            for (std::vector<int>::size_type i = 0; i != this->tokens.size(); i++) {
                f << this->tokens[i] << sep;
            }
            f.close();
        }

        void open(std::string filename){
            std::string s = "";
            std::ifstream f;
            f.open(filename);
            while(getline(f, s)){
                this->tokens.push_back(s);
            }
            f.close();
        }

};

std::ostream& operator<<(std::ostream& stdout, const File& obj){
    std::string start = "[", end = "]", delim = ", ";
    std::string s;
    if (obj.tokens.size() > 0){
        s += start;
        for (auto i: obj.tokens){
            s += i;
            if (i != obj.tokens.back()){
                s += delim;
            }
        }
        s += end;
    }
    else{
        s += start;
        s += end;
    }
    stdout << s;
    return stdout;
}

int main(){
    File file;
    file.open("save.txt");
    std::cout << file;
    
}
Topic archived. No new replies allowed.