【问题标题】:Overloading << and >> for STL map: "cannot bind lvalue"为 STL 映射重载 << 和 >>:“无法绑定左值”
【发布时间】:2016-07-01 17:08:02
【问题描述】:

我正在尝试使用 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)
     ^

谢谢!!

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      这里

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

      pair是const,所以pair.second也是const Point,不能匹配operator&lt;&lt;的参数类型Point&amp;

      operator&lt;&lt;Point的参数类型改为const引用:

      std::ostream& operator<<(std::ostream& os, const Point& p){
                                                 ~~~~~
          os << p.x << DELIM << p.y << DELIM;
          return os;
      }
      

      大多数情况下,传递给operator&lt;&lt; 的参数预计不会更改,因此最好将const&amp; 的类型声明为operator&lt;&lt;

      std::ostream& operator<<(std::ostream& os, const Point& p){
      std::ostream& operator<<(std::ostream& os, const std::map<std::string, Point>& m){
      

      【讨论】:

      • 我现在明白我的错误了。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多