tags:

views:

276

answers:

3

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.

+1  A: 

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.

Jon-Eric
+9  A: 

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.

Pavel Minaev
Thanks, the reference to ISO C++ standard is helpful.
Igor Krivokon
+1  A: 

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.

Adam Badura
Thanks! I figured the same about using bar as function, but thought maybe I'm missing something.
Igor Krivokon