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.
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.