Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getting a const_iterator from iterator [duplicate]

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 care
  • get_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.

like image 808
Armen Tsirunyan Avatar asked Jul 05 '11 16:07

Armen Tsirunyan


2 Answers

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.

like image 53
spraff Avatar answered Nov 04 '22 22:11

spraff


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.

like image 43
Nim Avatar answered Nov 04 '22 23:11

Nim