继续“不匹配'运算符<<' C ++

时间:2014-01-16 07:23:32

标签: c++

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

one
two one two
three three two one

我的输出应该如下:

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

一切正常,直到我尝试显示string,list(int)类型的映射,然后我得到整个“”与'operator<<'“错误不匹配。 这是我的代码,非常感谢任何帮助,谢谢!

#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;
}

2 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

最简单的解决方案:

// !!! 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. 之后才使用此新流
  4. 随意笨拙地婊子......

    自定义流to get you started的示例:

    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, ", "));,但我还没有遇到另一个方便的。 < / p>