Home Receive iterators as arguments and know class
Reply: 4

Receive iterators as arguments and know class

Tomer Amir
1#
Tomer Amir Published in 2018-01-10 17:57:31Z

I need to create a method that receives iterators as arguments and return a templated collection of the same type.

I created a minimal example the demonstrates my need:

#include <list>
#include <iostream>

using namespace std;

class A {
    int i;
public:
    A(int _i) : i(_i) {}

    operator int() {
        return i;
    }
};

class B {
    int i;
public:
    B(int _i) : i(_i) {}

    operator int() {
        return i;
    }
};

template <class T>
list<T> method(typename list<T>::iterator begin, typename list<T>::iterator end) {
    list<T> res; // I need the template class here

    for (; begin != end; begin++) {
        cout << *begin; // Whatever...
    }

    return res;
}

int main() {
    list<A> listA = {1, 2, 3};
    list<B> listB = {4, 5, 6};

    auto res1 = method(listA.begin(), listA.end()); // Cannot change
    auto res2 = method(listB.begin(), listB.end()); // Cannot change
}

This is not a working example, but I am looking for a way to make this work.

The important part is the method and it's arguments, and that it will return a templated class with T. So I can change the method as much as i want but the auto res1 = method(listA.begin(), listA.end()); should stay the same. (not my code)

How can I do something like this?

RiaD
2#
RiaD Reply to 2018-01-10 18:28:53Z

In this particular case (if you know that it's std::list) you can get value_type from iterator itself:

template <class T>
auto method(T begin, T end) {
    list<typename T::value_type> res; // I need the template class here

    for (; begin != end; begin++) {
        cout << *begin; // Whatever...
    }

    return res;
}

value_type = U only for std::list<U>

Maxim Egorushkin
3#
Maxim Egorushkin Reply to 2018-01-10 18:04:17Z

typename list<T>::iterator is a non-deduced context. You need to either pass the container itself or specify it as an explicit template argument.

Pete Becker
4#
Pete Becker Reply to 2018-01-10 18:17:12Z

Iterators designate a sequence; they do not have to be associated with a "collection". For example, you can create an iterator that reads input from the console.

If you want to restrict a function to only work with containers, then write it that way:

template <class T>
T f(const T& container) {
    // whatever; code that uses begin() and end()?
}
QuestionC
5#
QuestionC Reply to 2018-01-10 18:18:57Z

This isn't possible. You can have iterators that don't correspond to any container. The function that calls method should create an empty list and pass a back_inserter to the list as the third argument to method. Use std:copy as an example of what your method should look like.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.297584 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO