不断得到"与'操作员<<不匹配"C++

Keep getting "no match for 'operator<<' C++

本文关键字:lt 操作员 C++ 不匹配      更新时间:2023-10-16

我正在编写一个程序来从文件中读取文本,我需要打印出每个数字出现在文件中的位置。例如,.txt文件如下所示:

one
two one two
three three two one

我的输出应如下所示:

one: 0, 2, 7
two: 1, 3, 6
three: 4, 5

一切正常,直到我尝试显示字符串 list(int) 类型的映射,然后我得到整个"'运算符<<'不匹配"错误。这是我的代码,任何帮助将不胜感激,谢谢!

#include <iostream>
#include <fstream>
#include <string> 
#include <map>
#include <list>
#include <vector>
using namespace std;
int main()
{
    ifstream is("input.txt");
    if (is.fail())
    {
        cout << "File I/O error!" << endl;
        exit(1);
    }
    map<string, list<int> > m;
    string word;
    vector<string> v;
    list<int> l, x, y;
    while (is >> word)
    {
        v.push_back(word);
    }
    for (unsigned int i = 0; i < v.size(); ++i)
    {
        if (v[i] == "one")
            l.push_back(i);
        else if (v[i] == "two")
            x.push_back(i);
        else if (v[i] == "three")
            y.push_back(i);
    }
    m["One"] = l;
    m["Two"] = x;
    m["Three"] = y;
    for (map<string, list<int> >::iterator i = m.begin(); i != m.end(); ++i)
        cout << (*i).first << ", " << (*i).second << endl;
    return 0;
}

问题是当您尝试输出 (*i).second 时。由于i属于map<string, list<int> >::iterator (*i).second类型,因此list<int> c++不知道如何输出它。

您有两种选择 - 重载ostream& operator<<(ostream& out, const list<int>& l)或使用内部循环逐个输出元素。我个人推荐第二种选择,因为这种"流行"类型的运算符过载可能是危险的。

最简单的解决方案:

// !!! DO NOT DO THIS AT HOME OR AT ALL !!!
namespace std {
    template <typename T, typename A>
    ostream& operator<<(ostream& out, list<T, A> const& l) {
        if (l.empty()) { return out << "[]"; }
        out << '[';
        bool first = true;
        for (auto const& t: l) {
            if (first) { first = false; } else { out << ", "; }
            out << t;
        }
        return out << ']';
    } // operator<<
} // namespace std

不幸。。。严格禁止这样做(只允许专用化 std 命名空间中的现有模板,不能添加任何重载)。

因此,符合标准的最佳解决方案是:

  1. 声明您自己的新流(将所有内容转发到std::ostream&
  2. 为新流重载此运算符(在其命名空间中)
  3. 以后只使用这个新流

随意婊子笨拙...

帮助您入门的自定义流示例:

namespace project {
    class OStream {
    public:
        explicit OStream(std::ostream& out): _out(out) {}
        template <typename T>
        OStream& operator<<(T const& t) { print(*this, t); return *this; }
        template <typename T>
        void push(T const& t) { _out << t; }
    private:
        std::ostream& _out;
    }; // class OStream
    // Generic Operator (directly forwards to `std::ostream`)
    template <typename T>
    void print(OStream& out, T const& t) { out.push(t); }
    // STL Containers
    template <typename It>
    void print_range(OStream& out, It begin, It end) {
        if (begin == end) { out << "[]"; return; }
        out << '[' << *begin;
        for (++begin; begin != end; ++begin) { out << ", " << *begin; }
        out << ']';
    } // push_range
    template <typename T, typename A>
    void print(OStream& out, std::list<T, A> const& l) {
        print_range(out, l.begin(), l.end());
    } // operator<<
} // namespace project
// usage
int main() {
    std::list<int> example = { 1, 2, 3, 4 };
    project::OStream(std::cout) << example << "n";
}

注意:除了创建自定义流之外,还有其他解决方案,例如复制粘贴std::copy(example.begin(), example.end(), std::ostream_iterator<int>(std::cout, ", "));您需要打印列表的任何地方,但我还没有遇到另一个方便的解决方案。