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