在命名空间内的类中使用带有运算符重载的字符串流时"no match for ‘operator>>’"

"no match for ‘operator>>’" while using stringstream with operator overloading in a class inside a namespace

本文关键字:gt no match operator for 字符串 命名空间 重载 运算符      更新时间:2023-10-16

我正在尝试在命名空间内的类中重载>>运算符,但是一旦我尝试将其与字符串流一起使用,它就不起作用。这是我的代码的提炼版本:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
namespace Foo {
    class Bar {
    public:
        string str;
        friend istream& operator >>(istream& in, Bar& t);
    };
}
inline istream& operator >>(istream& in, Foo::Bar& t) {
    in >> t.str;
    return in;
}
int main() {
    Foo::Bar foo;
    stringstream("foo") >> foo;
    cout << foo.str << endl;
    return 0;
}

这是错误:

main.cpp:22:22: error: no match for ‘operator>>’ (operand types are ‘std::stringstream {aka std::__cxx11::basic_stringstream<char>}’ and ‘Foo::Bar’)

问题是这些其他方法的工作原理:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
namespace Foo {
    class Bar {
    public:
        string str;
        friend istream& operator >>(istream& in, Foo::Bar& t) {
            in >> t.str;
            return in;
        }
    };
}

int main() {
    Foo::Bar foo;
    stringstream("foo") >> foo;
    cout << foo.str << endl;
    return 0;
}
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class Bar {
public:
    string str;
    friend istream& operator >>(istream& in, Bar& t);
};
inline istream& operator >>(istream& in, Bar& t) {
    in >> t.str;
    return in;
}
int main() {
    Bar foo;
    stringstream("foo") >> foo;
    cout << foo.str << endl;
    return 0;
}

问题是,我不知道为什么第一种方法应该是错误的。如果有帮助,我正在 linux 上使用 g++ 编译器。有人可以帮助我了解发生了什么吗?

感谢Sam Varshavchik的提示(在上面的评论中(,我已经能够提出第一个版本的正确版本:

#include <iostream>
#include <string>
#include <sstream>
namespace Foo {
    class Bar {
    public:
        std::string str;
        friend std::istream& operator >>(std::istream& in, Bar& t);
    };
    std::istream& operator >>(std::istream& in, Bar& t);
}
std::istream& Foo::operator >>(std::istream& in, Foo::Bar& t) {
    in >> t.str;
    return in;
}
using namespace std;
int main() {
    Foo::Bar foo;
    stringstream("foo") >> foo;
    cout << foo.str << endl;
    return 0;
}

关键是确保运算符>>函数在同一范围内声明和定义。我仍然希望能够在命名空间大括号之外定义函数,所以我必须在命名空间内添加一个声明,以便编译器知道命名空间中应该有该函数。保持函数定义独立允许我将代码分成三个文件,main.cpp,foo.hpp和foo.cpp:

// main.cpp
#include <iostream>
#include <string>
#include <sstream>
#include "foo.hpp"
using namespace std;
int main() {
    Foo::Bar foo;
    stringstream("foo") >> foo;
    cout << foo.str << endl;
    return 0;
}
// foo.hpp
#ifndef FOO_HPP
#define FOO_HPP
#include <string>
#include <iostream>
namespace Foo {
    class Bar {
    public:
        std::string str;
        friend std::istream& operator >>(std::istream& in, Bar& t);
    };
    std::istream& operator >>(std::istream& in, Bar& t);
}
#endif
// foo.cpp
#include "foo.hpp"
std::istream& Foo::operator >>(std::istream& in, Foo::Bar& t) {
    in >> t.str;
    return in;
}

无论如何,非常感谢您的帮助!谢谢你没有亲手喂我一个解决方案;通过自己弄清楚来学习要好得多,即使我确实得到了一些帮助,为我指明了正确的方向。