Hi!
This was detected by profiling. I expected the code below
to have a rather cheap std::distance call because my iterator
was tagged as random_access.
gcc-4.0.3 (cygwin) and VC8 IMHO choose the wrong std::distance algorithm,
but why? The stuff compiles even when distance_to is not defined.
Maybe I misunderstood the docs, especially the passage
<cite url="http://boost.org/libs/iterator/doc/iterator_facade.html">
[...]
where iterator-category is defined as follows:
iterator-category(C,R,V) :=
if (C is convertible to std::input_iterator_tag
|| C is convertible to std::output_iterator_tag
)
return C
else if (C is not convertible to incrementable_traversal_tag)
the program is ill-formed
else return a type X satisfying the following two constraints:
[..]
</cite>
Please explain and fix the code below.
Markus
#include
#include
#include <cstddef>
#include <iterator>
#include <iostream>
template
class signal_iter
: public boost::iterator_facade
,
ValueT,
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
boost::random_access_traversal_tag,
ValueT,
SizeT>
{
public:
typedef signal_iter my_own_t;
inline signal_iter(IndexOperatorT IndexOperator, SizeT index)
: m_IndexOperator(IndexOperator)
, m_index(index)
{}
// quick and dirty with a dangling reference :-(
inline signal_iter()
: m_IndexOperator(IndexOperatorT())
, m_index(0)
{}
inline SizeT index() const
{
return m_index;
}
private:
friend class boost::iterator_core_access;
inline void increment()
{
++m_index;
}
inline void decrement()
{
--m_index;
}
inline void advance(SizeT i)
{
m_index += i;
}
inline SizeT distance_to(signal_iter const& other) const
{
return other.index() - m_index;
}
inline bool equal(signal_iter const& other) const
{
return (other.index() == m_index);
}
inline ValueT dereference() const
{
return m_IndexOperator(m_index);
}
protected:
IndexOperatorT m_IndexOperator;
SizeT m_index;
};
// stripped down demo
class Demo
{
static const std::size_t mysize_ = 20;
typedef std::size_t size_type;
typedef double value_type;
double data_[mysize_];
public:
double operator[](std::size_t i)
{
return data_[i];
}
typedef boost::_bi::bind_t
,
boost::_bi::list2,
boost::arg<1> > > bind_type;
typedef signal_iter
const_iterator;
const_iterator begin()
{
return const_iterator
(boost::bind(&Demo::operator[], this, _1), 0);
}
const_iterator end()
{
return const_iterator
(boost::bind(&Demo::operator[], this, _1), mysize_);
}
};
int main()
{
Demo demo;
std::cout << std::distance(demo.begin(), demo.end())<< std::endl;
}