Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function that takes an STL iterator over ANY container of a elements of a specific type

Tags:

c++

How would I define a function that takes as input an iterator over any type of STL container, but only to those of a specific templated type. For example:

Any iterator of the form std::list<Unit*>::iterator or std::vector<Unit*>::iterator

I would just define the function to take std::list<Unit*>::iterator, but if we switch to a different STL container, I don't want to have to change my code.

Is there a way to do this with templates or otherwise?

like image 720
RyanG Avatar asked Dec 04 '10 17:12

RyanG


People also ask

Which STL function returns an iterator?

5. prev() :- This function returns the new iterator that the iterator would point after decrementing the positions mentioned in its arguments. 6.

What is the use of iterate over container in STL?

An iterator is used to point to the memory address of the STL container classes. For better understanding, you can relate them with a pointer, to some extent. Iterators act as a bridge that connects algorithms to STL containers and allows the modifications of the data present inside the container.

Which function is used to get a move iterator from a container?

struct vec{ iterator begin() ; const_iterator begin() const; };

What is the use of iterator while using containers?

An iterator is an object (like a pointer) that points to an element inside the container. We can use iterators to move through the contents of the container. They can be visualised as something similar to a pointer pointing to some location and we can access content at that particular location using them.


2 Answers

You could use a SFINAE construct such as boost::enable_if which verifies if the nested typedef iterator::value_type is indeed of the appropriate type.

template<class T, class Iterator>
typename boost::enable_if<boost::is_same<typename Iterator::value_type, T> >::type
    f(Iterator i)
{
    /* ... */
}

int main()
{
    std::list<int> l;
    std::vector<int> v;

    f<int>(l.begin()); // OK
    f<int>(v.begin()); // OK

    std::vector<float> v2;
    f<int>(v2.begin()); /* Illegal */
}

This is what I understand from "a function that takes as input an iterator over any type of STL container, but only to those of a specific templated type", but my interpretation might be wrong.

like image 68
icecrime Avatar answered Oct 17 '22 21:10

icecrime


In addition to the existing answers relying on SFINAE, a simpler approximation would be to simply define the function to take an arbitrary template type as the iterator:

template <typename Iter>
void function(Iter first, Iter last){
  Unit* val = *first;
}

This has a few downsides. Unlike the SFINAE solution (such as boost::enable_if), this doesn't give you exactly what you asked for. This compiles as long as an object of type Iter can be dereferenced yielding a value convertible to Unit*, which isn't quite the same thing. You have no guarantee that Iter is a completely STL-compliant iterator (it may just be another type which defines operator*), or that its value type is Unit* precisely.

On the other hand, it's much simpler.

like image 24
jalf Avatar answered Oct 17 '22 19:10

jalf