Tomer Amir
Tomer Amir

Reputation: 1585

Receive iterators as arguments and know class

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?

Upvotes: 0

Views: 54

Answers (4)

RiaD
RiaD

Reputation: 47619

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>

Upvotes: 2

QuestionC
QuestionC

Reputation: 10064

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.

Upvotes: 1

Pete Becker
Pete Becker

Reputation: 76245

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()?
}

Upvotes: 1

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136208

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.

Upvotes: 1

Related Questions