Unfortunatly that solution is not possible in my case as the function in question is an overloaded operator.
Thanks anyway. I've solved it via template metaprogramming :)
So in case anyone ever needs to concatenate two containers or anything like that:
Code:
#ifndef _MOREITER_HPP_SR_H_
#define _MOREITER_HPP_SR_H_
#include <iterator>
#include <boost/iterator.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>
namespace boost
{
namespace internal
{
// Gets the lesser iterator category of the two arguments
// Possible combinations:
// Combination Handled By Result
// II IU I
// FI FI I
// BI UU IB -> I
// RI UU IR -> I
// IF IU I
// FF FU F
// BF UU FB -> F
// RF UU FR -> F
// IB IU I
// FB FU F
// BB BB B
// RB UU BR -> B
// IR IU I
// FR FU F
// BR BR B
// RR RR R
// A version that compiles without partial spec. would have to explicitly
// handle more cases.
// UU
template<typename LCAT, typename RCAT>
struct lesser_category
{
typedef typename lesser_category<RCAT, LCAT> type;
};
// IU
template<typename RCAT>
struct lesser_category<std::input_iterator_tag, RCAT>
{
typedef std::input_iterator_tag type;
};
// FU
template<typename RCAT>
struct lesser_category<std::forward_iterator_tag, RCAT>
{
typedef std::forward_iterator_tag type;
};
// FI
template<>
struct lesser_category<std::forward_iterator_tag,
std::input_iterator_tag>
{
typedef std::input_iterator_tag type;
};
// BB
template<>
struct lesser_category<std::bidirectional_iterator_tag,
std::bidirectional_iterator_tag>
{
typedef std::bidirectional_iterator_tag type;
};
// BR
template<>
struct lesser_category<std::bidirectional_iterator_tag,
std::random_access_iterator_tag>
{
typedef std::bidirectional_iterator_tag type;
};
// RR
template<>
struct lesser_category<std::random_access_iterator_tag,
std::random_access_iterator_tag>
{
typedef std::random_access_iterator_tag type;
};
}
template<typename FirstIter, typename SecondIter,
typename Category = internal::lesser_category<
typename std::iterator_traits<FirstIter>::iterator_category,
typename std::iterator_traits<SecondIter>::iterator_category>::type >
class concatenation_iterator
: public iterator<Category, typename std::iterator_traits<FirstIter>::value_type,
typename std::iterator_traits<FirstIter>::distance_type,
typename std::iterator_traits<FirstIter>::pointer,
typename std::iterator_traits<FirstIter>::reference>
{
public:
typedef FirstIter first_iterator_type;
typedef SecondIter second_iterator_type;
typedef concatenation_iterator<first_iterator_type, second_iterator_type,
Category> self;
private:
FirstIter begin1, end1;
SecondIter begin2;
public:
// Creates a begin iterator
concatenation_iterator(const FirstIter& b1, const FirstIter &e1, const SecondIter &b2)
: begin1(b1), end1(e1), begin2(b2)
{}
// Creates an end iterator
concatenation_iterator(const FirstIter &e1, const SecondIter &e2)
: begin1(e1), end1(e1), begin2(e2)
{}
reference operator *() { return begin1 == end1 ? *begin2 : *begin1; }
pointer operator ->() { return begin1 == end1 ? &*begin2 : &*begin1; }
self & operator ++() { if(begin1 != end1) ++begin1; else ++begin2; return *this; }
// Test the moving iterators
friend bool operator ==(const self &x, const self &y) {
return x.begin1 == y.begin1 && x.begin2 == y.begin2;
}
friend bool operator !=(const self &x, const self &y) {
return x.begin1 != y.begin1 || x.begin2 != y.begin2;
}
// This needs more thinking about - partial specialization?
// I may not use a proxy object for this if it's not
// an input iterator.
// But if one of the contained iterators is an input iterator
// and uses shallow copy then this implementation fails.
// Use template metaprogramming to specify the return type.
class postinc_proxy {
value_type el;
public:
explicit postinc_proxy(const self &) : el(*i) {}
value_type operator *() const { return el; }
};
typedef typename mpl::if_<is_same<Category, std::input_iterator_tag>,
postinc_proxy, self>::type postinc_ret;
postinc_ret operator ++(int) { postinc_ret t(*this); ++*this; return t; }
};
}
#endif