与插入迭代器和重载运算符相关的C ++ STL问题

时间:2010-04-21 18:23:08

标签: c++ stl

#include <list>
#include <set>
#include <iterator>
#include <algorithm>

using namespace std;

class MyContainer {
public:
 string value;

    MyContainer& operator=(const string& s) {
        this->value = s;
        return *this;
    }
};

int main() 
{
    list<string> strings;
    strings.push_back("0");
    strings.push_back("1");
    strings.push_back("2");

    set<MyContainer> containers;
    copy(strings.begin(), strings.end(), inserter(containers, containers.end()));
}

前面的代码无法编译。在标准C ++方式中,错误输出是冗长且难以理解的。关键部分似乎是这个......

/usr/include/c++/4.4/bits/stl_algobase.h:313:错误:'__result.std :: insert_iterator :: operator *中没有匹配'operator ='[与_Container = std :: set,std :: allocator&gt;]()= __first.std :: _ List_iterator :: operator * [with _Tp = std :: basic_string,std :: allocator&gt;]()'

...我实际上意味着没有定义所需的赋值运算符。我看了一下insert_iterator的源代码,并注意到它已经重载了赋值运算符。复制算法必须使用insert iterators重载赋值运算符来完成它的工作(?)。

我想这是因为我的输入迭代器是在一个字符串容器上,而我的输出迭代器是在MyContainers的容器上,重载的insert_iterator赋值运算符不再起作用。

这是我最好的猜测,但我可能错了。

那么,为什么这不起作用,我怎样才能完成我想要做的事情呢?

3 个答案:

答案 0 :(得分:4)

使用构造函数(将更有意义而不是赋值)将起作用:

class MyContainer {
public:
 string value;

    MyContainer(const string& s): value(s) {
    }
};

然后第二个问题是该集合还要求其内容具有可比性。

至于原因,insert_iterator通过重载operator=来工作:

insert_iterator<Container>& operator= (typename Container::const_reference value);

正如您所看到的,右侧值必须是容器的值类型或者可以隐式转换为它,这正是(非显式)构造函数实现的,而赋值运算符则不是。


从技术上讲,你也可以通过提供合适的转换函数来使其工作而不改变类(例如,如果你不想要非显式构造函数):

MyContainer from_string(const std::string& s)
{
    MyContainer m;
    m = s;    //or any other method how to turn a string into MyContainer
    return m;
}

可以与std::transform一起使用:

transform(strings.begin(), strings.end(), inserter(containers, containers.end()), from_string);

答案 1 :(得分:3)

您需要添加:
1.接受字符串的构造函数(您试图将字符串添加到可以包含MyContainer对象的容器中) 2. bool运算符&lt; (set默认使用它来比较元素)
例如:

class MyContainer
{
  public:
   MyContainer(const string& v):value(v){};
};
bool operator <(const MyContainer &c1, const MyContainer &c2)
{
return c1.value <c2.value;
}

答案 2 :(得分:1)

问题是双重的:

  1. 您正在尝试填充一组MyContainer个对象
  2. ...来自string个对象的列表。
  3. copy()算法尝试将每个string对象转换为MyContainer对象。在C ++中添加类MyContainer的类string转换支持到类型MyContainer,您需要添加一个带有string类型参数的构造函数:

    struct MyContainer {
        MyContainer(const string& s) : value(s) { }
        bool operator<(const MyContainer& o) const { return value < o.value; }
    
    private:
        string s;
    };
    

    您不需要赋值运算符,因为编译器可以通过copy-constructor完成复制:将string转换为MyContainer,然后使用默认赋值运算符指定一个MyContainer反对另一个。但是,您需要operator<(),因为C ++集已经过排序。