Boost logo

Boost Users :

Subject: Re: [Boost-users] iterator_facade Boost 1.57
From: Matei David (matei_at_[hidden])
Date: 2014-11-07 12:53:06


On Tue, 04 Nov 2014 14:07:09 +0000 (UTC)
gast128 wrote:

> Dear all,
>
> Just trying out 1.57, since we are already 5 releases behind due to
> all kinds of compilation errors with Boost and our software. Below
> simplified code doesn't compile on vs2010:
>
> template <typename DerivedType>
> struct IteratorFacade : public boost::iterator_facade<DerivedType,
> int, std::random_access_iterator_tag>
> {
> typedef boost::iterator_facade<DerivedType, int,
> std::random_access_iterator_tag> base;
>
> IteratorFacade ();
> virtual ~IteratorFacade ();
>
> friend class boost::iterator_core_access;
>
> reference dereference () const;
> };
>
> struct MyIteratorFacade : IteratorFacade<MyIteratorFacade>
> {
> };
>
> What do I wrong?

Hi,

I'm gcc 4.9.1 on Ubuntu 14.04.

The reason this doesn't compile is that the "reference" typedef is
contained in the glue class boost::iterator_facade, which is a base
class of IteratorFacade<MyIteratorFacade>. When you write "reference"
inside the later, the name is not being looked up in the base class.
So you should write:
typename base::reference dereference() const;

If you want to use "reference" in many places in IteratorFacade<>,
pull the typedef from its base with:
typedef typename base::reference reference;
or, if using C++11:
using typename base::reference;

Note: whether you pull it up or not, you can always get the typedef as
IteratorFacade<...>::reference, or MyIteratorFacade::reference in your
case. (See the example below, where I'm not pulling it up, but I
can still find it.)

I would also add the observation that your construct creates an unusual
derivation. Usually, the iterator class you want to define has
boost::iterator_facade as its direct base. In your case,
boost::iterator_facade is the base of the base of your iterator class
(so, 2 levels down):

MyIteratorFacade
 : IteratorFacade<MyIteratorFacade>
   : boost::iterator_facade<MyIteratorFacade, ...>

I'm not sure this would cause any problems, just be on the lookout for
missing constructors.

For example, this compiles just fine for me:

#include <type_traits>
#include <boost/iterator/iterator_facade.hpp>

struct MyIteratorFacade
    : public boost::iterator_facade<MyIteratorFacade, int,
          std::random_access_iterator_tag>
{
    typedef boost::iterator_facade<MyIteratorFacade, int,
        std::random_access_iterator_tag> base;
    MyIteratorFacade ();
    virtual ~MyIteratorFacade ();
    friend class boost::iterator_core_access;
    typename base::reference dereference() const;
};

static_assert(std::is_same< MyIteratorFacade::value_type, int >::value,
"MyIteratorFacade::value_type != int");
static_assert(std::is_same< MyIteratorFacade::reference, int& >::value,
"MyIteratorFacade::reference != int&");
static_assert(std::is_same< MyIteratorFacade::pointer, int* >::value,
"MyIteratorFacade::pointer != int*");
static_assert(std::is_same<
std::iterator_traits<MyIteratorFacade>::value_type, int >::value,
"iterator_traits<MyIteratorFacade>::value_type != int");
static_assert(std::is_same<
std::iterator_traits<MyIteratorFacade>::reference, int& >::value,
"iterator_traits<MyIteratorFacade>::reference != int&");
static_assert(std::is_same<
std::iterator_traits<MyIteratorFacade>::pointer, int* >::value,
"iterator_traits<MyIteratorFacade>::pointer != int*");

I compile with:
g++ -Wall -Wextra -pedantic -std=c++11 -I${BOOST_INCLUDE_1_57}
-c

(I'm only using c++11 for static_assert.)

M


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net