重载<<和>>对于STL地图:"无法绑定左值"

时间:2016-03-16 01:19:13

标签: c++ c++11 gcc stl

我正在尝试使用fstream将包含自定义对象的STL地图保存到文件中。我正在使用<<和>>运算符重载。

#include <iostream>
#include <string>
#include <map>
#include <fstream>

#define DELIM '/'

struct Point{
public:
    int x, y;
};
//operator overloads for point
std::istream& operator>>(std::istream& is, Point& p){
    std::string input;
    std::getline(is, input, DELIM);
    p.x = std::stoi(input);
    std::getline(is, input, DELIM);
    p.y = std::stoi(input);
    return is;
}
std::ostream& operator<<(std::ostream& os, Point& p){
    os << p.x << DELIM << p.y << DELIM;
    return os;
}

//operator overloads for map<string, point>
std::istream& operator>>(std::istream& is, std::map<std::string, Point>& m){
    std::string input;
    std::getline(is, input, DELIM);
    int map_size = std::stoi(input);
    for(int i = 0; i < map_size; i++){
        std::getline(is, input, DELIM);
        Point p; is >> p;
        m[input] = p;
    }
    return is;
}
std::ostream& operator<<(std::ostream& os, std::map<std::string, Point>& m){
    os << m.size() << DELIM;
    for(const auto& pair : m){
        os << pair.first << DELIM;
        os << pair.second;
    }
    return os;
}


int main(){
    Point p1;
    p1.x = 1; p1.y = 2;
    Point p2;
    p2.x = 100; p2.y = 150;

    std::map<std::string, Point> map;
    map["p1"] = p1;
    map["p2"] = p2;


    return 0;
}

当我尝试编译此文件时,出现以下错误:

test.cpp: In function 'std::ostream& operator<<(std::ostream&, std::map<std::basic_string<char>, Point>&)':
test.cpp:44:14: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
   os << pair.second;

知道怎么解决这个问题吗?我之前使用模板遇到了这个问题,但是这里没有使用模板。关于SO的其他答案也涉及模板,并没有帮助我。为什么会发生这种情况的解释也将受到赞赏!


我用来编译的命令:(MinGW,gcc 4.8.1)

g++ test.cpp -o test -std=c++11 -Wall

完整的错误消息:

test.cpp: In function 'std::ostream& operator<<(std::ostream&, std::map<std::basic_string<char>, Point>&)':
test.cpp:44:14: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
   os << pair.second;
              ^
In file included from c:\mingw\lib\gcc\x86_64-w64-mingw32\4.8.1\include\c++\iostream:39:0,
                 from test.cpp:1:
c:\mingw\lib\gcc\x86_64-w64-mingw32\4.8.1\include\c++\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 = Point]'
     operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
     ^

谢谢!

2 个答案:

答案 0 :(得分:8)

下面

for(const auto& pair : m){
    os << pair.first << DELIM;
    os << pair.second;
}

pair是常量,因此pair.second也是const Point,它不能与Point&的参数类型operator<<匹配。

Point的{​​{1}}的参数类型更改为const引用:

operator<<

大多数情况下,传递给std::ostream& operator<<(std::ostream& os, const Point& p){ ~~~~~ os << p.x << DELIM << p.y << DELIM; return os; } 的参数不会被更改,因此将operator<<的类型声明为const&是一种很好的做法。

operator<<

答案 1 :(得分:2)

传递给重载<<运算符的参数应该是常量引用,而不是可变引用。