Possible Duplicate:
Obtaining const_iterator from iterator
I want to write a metafunction which returns the corresponding const_iterator from an iterator
template <class Iterator>
struct get_const_iterator
{
    typedef ??? type;
};
get_const_iterator<int*>::type must be const int*
get_const_iterator<const int*>::type must be const int* get_const_iterator<int* const>::type must be const int* or const int* const, I don't   careget_const_iterator<std::list<char>::iterator>::type must be std::list<char>::const_iterator
etc.
Can this be done with iterator_traits or without them? 
Edit: Let's assume that if 2 container have the same iterator type then they also have the same const_iterator type. I think this is a reasonable assumption, although theoretically not entirely correct one.
You can do it in C++0x
template <typename Container>
Container container (typename Container :: iterator);
template <typemame Iterator>
struct get_const_iterator
{
    typedef decltype (container (Iterator())) :: const_iterator type;
};
Although I'm starting to agree with Steve -- this is not a general solution since different containers may have the same iterator types.
You can do it in the current standard, if you are willing to partially specialize for the containers, as in...
#include <vector>
#include <list>
#include <iterator>
// default case
template <typename Iterator, typename value_type, typename container_test = Iterator>
struct container
{
  typedef Iterator result;
};
// partial specialization for vector
template <typename Iterator, typename value_type>
struct container<Iterator, value_type, typename std::vector<value_type>::iterator>
{
  typedef typename std::vector<value_type>::const_iterator result;
};
// partial specialization for list, uncomment to see the code below generate a compile error
/* template <typename Iterator, typename value_type>
struct container<Iterator, value_type, typename std::list<value_type>::iterator>
{
  typedef typename std::list<value_type>::const_iterator result;
}; */
// etc.
template <typename Iterator>
struct get_const
{
  typedef typename container<Iterator, typename std::iterator_traits<Iterator>::value_type>::result type;
};
int main(void)
{
  std::list<int> b;
  b.push_back(1);
  b.push_back(2);
  b.push_back(3);
  get_const<std::list<int>::iterator>::type it1 = b.begin(), end1 = b.end();
  for(; it1 != end1; ++it1)
    ++*it1; // this will be okay
  std::vector<int> f;
  f.push_back(1);
  f.push_back(2);
  f.push_back(3);
  get_const<std::vector<int>::iterator>::type it = f.begin(), end = f.end();
  for(; it != end; ++it)
    ++*it; // this will cause compile error
}
Of course, will repeat Steve's point above, and also the requirement is that iterator_traits for your iterator exists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With