Общая функция для выравнивания контейнера контейнеров - PullRequest
7 голосов
/ 20 июня 2011

Я пытаюсь лучше понять итераторы и универсальные функции. Я подумал, что было бы полезно написать функцию, которая преобразует container1 < container2 <type> > в container3 <type>. Например, он должен иметь возможность конвертировать vector< deque<int> > в list<int>.

Я полагал, что весь доступ к контейнеру должен осуществляться через итераторы, подобно функциям в <algorithm>.

Вот мой код:

#include <iterator>
#include <algorithm>

// COCiter == Container of Containers Iterator
// Oiter == Output Iterator
template <class COCiter, class Oiter>
void flatten (COCiter start, COCiter end, Oiter dest)
{
    using namespace std;

    while (start != end) {
        dest = copy(start->begin(), start()->end(), dest);
        ++start;
    }
}

Но когда я пытаюсь вызвать его в следующем коде:

int main ()
{
    using namespace std;

    vector< vector<string> > splitlines;
    vector<string> flat;

    /* some code to fill SPLITLINES with vectors of strings */

    flatten(splitlines.begin(), splitlines.end(), back_inserter(flat));
}

Я получаю огромное сообщение об ошибке шаблона C ++, undefined reference to void flatten< ... pages of templates ...

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

Ответы [ 2 ]

8 голосов
/ 20 июня 2011

Я нашел проблему.Благодаря SFINAE (ошибка замены не является ошибкой) ваш компилятор не смог найти правильный шаблон, потому что вы пытаетесь вызвать operator() на start, набрав start() (возможно, опечатка).Попробуйте это:

#include <iterator>
#include <algorithm>

// COCiter == Container of Containers Iterator
// Oiter == Output Iterator
template <class COCiter, class Oiter>
void flatten (COCiter start, COCiter end, Oiter dest) {
    while (start != end) {
        dest = std::copy(start->begin(), start->end(), dest);
        ++start;
    }
}
0 голосов
/ 02 июня 2018

std::accumulate может сделать это за вас. Вам нужно собрать содержимое каждого из внутренних векторов во внешний вектор.

vector<vector<int>> v_of_v;
vector<int> v = std::accumulate(
    v_of_v.begin(), v_of_v.end(),
    vector<int>(),
    [](vector<int> a, vector<int> b) {
        a.insert(a.end(), b.begin(), b.end());
        return a;
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...