Igor Krivokon
Igor Krivokon

Reputation: 10275

Is it possible to get the value type from an arbitrary iterator (C++)?

I have a class

template <typename Iterator, typename Value>
class Foo {
 public:
  Foo(const Iterator& it) { ... }
  ...
 private:
   map<Value, int> m_;
  }
};

Is there any way to get rid of Value in the template? The Iterator may or may not be an STL iterator, but it's guaranteed that *it type is Value.

I know about iterator_traits<T>::value_type for STL iterators, but wonder if there's any way to get Value type automatically for an arbitrary Iterator type?

One trick I'm thinking about - say, we have a helper class

template <typename Iterator, typename Value>
class Bar {
 public:
  Bar(const Iterator& dummy_iterator, const Value& dummmy_value) {}
  ...
};

Then if we instantiate Bar as Bar(it, *it), the type of Value will be known inside Bar. But I can't find a good way to combine Bar with Foo.

Upvotes: 14

Views: 3881

Answers (3)

Adam Badura
Adam Badura

Reputation: 5339

As to getting value type of iterator previous answers were correct.

But there is more. The trick you are thinking of would not work with class. If Bar was a function like:

template <typename Iterator, typename Value>
void bar(const Iterator& dummy_iterator, const Value& dummmy_value) {}

then type deduction would work for bar(it, *it) and you would have the value type inside of bar. (But keep in mind that to use this trick you would still have to have a dereferencable iterator it which is not always good - how to deal with empty sequence then?)

Using a class Bar you would have to provide the template arguments Iterator and Value manually as there is no type deduction for classes and using Bar(it, *it) would no compile.

Upvotes: 1

Pavel Minaev
Pavel Minaev

Reputation: 101585

Any iterator should provide iterator_traits<Iterator>::value_type. If it does not, then it is not an iterator. ISO C++ 2003 24.3.1[lib.iterator.traits] "Iterator traits":

To implement algorithms only in terms of iterators, it is often necessary to determine the value and difference types that correspond to a particular iterator type. Accordingly, it is required that if Iterator is the type of an iterator, the types

iterator_traits<Iterator>::difference_type
iterator_traits<Iterator>::value_type
iterator_traits<Iterator>::iterator_category

be defined as the iterator’s difference type, value type and iterator category, respectively.

Aside from that, there's no general way to obtain a type of an arbitrary C++ expression. C++0x will rectify it by providing decltype.

Upvotes: 18

Jon-Eric
Jon-Eric

Reputation: 17275

Sorry. The correct way to get rid of Value is to use iterator_traits as you suggested.

If your non-STL iterator is a naked pointer, then you get correct iterator_traits typedefs for free. Otherwise the non-STL iterator class must define the correct typedefs.

See the iterator traits documentation for more information.

Upvotes: 1

Related Questions