C ++ STL вопрос, связанный с вставкой итераторов и перегруженных операторов - PullRequest
1 голос
/ 21 апреля 2010
#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: ошибка: нет совпадения для 'operator =' в '__result.std :: insert_iterator :: operator * [with _Container = std :: set, std :: allocator>] () = __first.std :: _ List_iterator :: operator * [с _Tp = std :: basic_string, std :: allocator>] () '

... что я понимаю, что необходимый оператор присваивания не определен. Я взглянул на исходный код для insert_iterator и заметил, что он перегружен оператором присваивания. Алгоритм копирования должен использовать перегруженный оператор присваивания итераторов для выполнения своей работы (?).

Полагаю, что поскольку мой входной итератор находится в контейнере строк, а мой выходной итератор - в контейнере MyContainers, перегруженный оператор присваивания insert_iterator больше не может работать.

Это мое лучшее предположение, но я, вероятно, ошибаюсь.

Итак, почему именно это не работает и как я могу выполнить то, что я пытаюсь сделать?

Ответы [ 3 ]

4 голосов
/ 21 апреля 2010

Что бы сработало, было бы использовать конструктор (который имел бы больше смысла вместо присваивания):

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);
3 голосов
/ 21 апреля 2010

Вам необходимо добавить:
1. Конструктор, который принимает строку (вы пытаетесь добавить строку в контейнер, который может содержать объекты MyContainer).
2. bool operator <(set использует его по умолчанию для сравнения элементов) <br>Например:

class MyContainer
{
  public:
   MyContainer(const string& v):value(v){};
};
bool operator <(const MyContainer &c1, const MyContainer &c2)
{
return c1.value <c2.value;
}
1 голос
/ 21 апреля 2010

Проблема двоякая:

  1. Вы пытаетесь заполнить набор MyContainer объектов
  2. ... из списка string объектов.

Алгоритм 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 ++ отсортированы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...