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

发布于 2024-08-29 13:23:50 字数 1148 浏览 1 评论 0原文

#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=' 不匹配 [with _Container = std::set, std::分配器 >]() = __first.std::_List_iterator::operator* [with _Tp = std::basic_string, std::allocator >]()'

...我的解释是,所需的赋值运算符未定义。我查看了 insert_iterator 的源代码,发现它重载了赋值运算符。复制算法必须使用插入迭代器重载赋值运算符来完成其工作(?)。

我猜想,因为我的输入迭代器位于字符串容器上,而输出迭代器位于 MyContainers 容器上,所以重载的 insert_iterator 赋值运算符无法再工作。

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

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

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

The preceeding code does not compile. In standard C++ fashion the error output is verbose and difficult to understand. The key part seems to be this...

/usr/include/c++/4.4/bits/stl_algobase.h:313: error: no match for ‘operator=’ in ‘__result.std::insert_iterator::operator* [with _Container = std::set, std::allocator >]() = __first.std::_List_iterator::operator* [with _Tp = std::basic_string, std::allocator >]()’

...which I interpet to mean that the assignment operator needed is not defined. I took a look at the source code for insert_iterator and noted that it has overloaded the assignment operator. The copy algorithm must uses the insert iterators overloaded assignment operator to do its work(?).

I guess that because my input iterator is on a container of strings and my output iterator is on a container of MyContainers that the overloaded insert_iterator assignment operator can no longer work.

This is my best guess, but I am probably wrong.

So, why exactly does this not work and how can I accomplish what I am trying to do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不美如何 2024-09-05 13:23:50

有效的方法是使用构造函数(这比赋值更有意义):

class MyContainer {
public:
 string value;

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

那么第二个问题是 set 还要求其内容具有可比性。

至于原因,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);

What would work would be using the constructor (which would make more sense instead of the assignment):

class MyContainer {
public:
 string value;

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

Then the second problem is that set also requires its contents to be comparable.

As to the cause, insert_iterator works by overloading operator=:

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

As you can see, the righthand value must be either the value type of the container or implicitly convertible to it, which is exactly what a (non-explicit) constructor achieves and the assignment operator doesn't.


Technically you could also make it work without changing the class (e.g if you don't want an non-explicit constructor) by providing a suitable conversion function:

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

which can be used with std::transform:

transform(strings.begin(), strings.end(), inserter(containers, containers.end()), from_string);
嘿嘿嘿 2024-09-05 13:23:50

您需要添加:
1. 接受字符串的构造函数(您正在尝试将字符串添加到可以包含 MyContainer 对象的容器)。
2. 布尔运算符 < (set默认使用它来比较元素)
例如 :

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

You need to add:
1. Constructor that takes string (you are trying to add string to container that can contain MyContainer objects).
2. bool operator < (set uses it by default to compare elements)
For instance :

class MyContainer
{
  public:
   MyContainer(const string& v):value(v){};
};
bool operator <(const MyContainer &c1, const MyContainer &c2)
{
return c1.value <c2.value;
}
野の 2024-09-05 13:23:50

问题是双重的:

  1. 您试图
  2. string 对象列表中填充一组 MyContainer 对象。

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

不需要赋值运算符,因为编译器可以通过复制构造函数完成复制:将 string 转换为 MyContainer然后使用默认的赋值运算符将一个 MyContainer 对象分配给另一个对象。但是,您将需要一个operator<(),因为 C++ 集合是排序的。

The problem is twofold:

  1. You're trying to fill a set of MyContainer objects
  2. ... from a list of string objects.

The copy() algorithm tries to convert each string object to a MyContainer object. In C++ to add to class MyContainer conversion support from type string to type MyContainer you need to add a constructor that takes a parameter of type string:

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

private:
    string s;
};

You don't need an assignment operator, because the compiler can get the copying done by the copy-constructor: convert a string to a MyContainer and then use the default assignment operator to assign one MyContainer object onto the other. You will, however need an operator<() because C++ sets are sorted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文