Search code examples
c++boost

boost::enable_if enabler() related to the tutorial on creating an iterator with boost::iterator_facade


So... looking at this code fragment:

    #include <boost/iterator/iterator_facade.hpp>
    #include <boost/type_traits/is_convertible.hpp>
    #include <boost/utility/enable_if.hpp>
    
    template <class Value>
    class LMI
      : public boost::iterator_facade<LMI<Value>, Value, boost::forward_traversal_tag>
    {
    private:
      int xsize, ysize, x, y;
      Level *level {0};             // iterator invalid if level == 0

    public:
      LMI(LMI<OtherValue> const &L, 
          typename boost::enable_if<boost::is_convertible<OtherValue*,Value*>,
                                    enabler>::type = enabler())
        : xsize {L.xsize}, ysize {L.ysize}, x {L.x}, y {L.y}, level {L.level}
      {};
    };

The compiler complains that there is no identifier 'enabler' ... which all comes from the boost example documentation at https://www.boost.org/doc/libs/1_72_0/libs/iterator/doc/iterator_facade.html#telling-the-truth

I'm at the point where I realize that enable_if and is_convertible are magic templates that determine if this converting constructor is created (which the tutorial as much says), but I don't see any advice on this "enabler()" function --- is the tutorial incorrect in this usage? Has the usage changed since the tutorial was written?

It may help the readers to know that this template is used thusly:

typedef LMI<Tile> Level_Map_Iterator;
typedef LMI<Tile const> cLevel_Map_Iterator;

... the point being that while creating LMI it will create the converting constructor and while creating LMI it will not.


Solution

  • So... sheepishly, if I add

    struct enabler {};
    

    to the private section of the class template, all is good. Doesn't exactly explain how this works --- but I'm happy with the secret sauce for now. Obviously, I was adapting the tutorial example to my own work, sigh.