$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [iterator] iterator_facade reference type problem
From: Phil Endecott (spam_from_boost_dev_at_[hidden])
Date: 2010-01-15 06:37:52
Jeffrey Hellrung wrote:
> Phil Endecott wrote:
>> I've done some more experiments, and it seems to work with
>> std::pair<const KEY, value&> if i write (*iter).second rather than
>> iter->second.
>>
>> Looking at the iterator_facade source, operator-> calls operator* and
>> passes the result to operator_arrow_result::make(). This takes its
>> address and, because std::pair<const KEY,VALUE&> is not a reference, it
>> tries to convert it to operator_arrow_proxy<...>. This fails because
>> std::pair<const KEY,VALUE&> is not convertible to std::pair<KEY,VALUE>.
>>
>> I think I just want operator-> to return a pointer to my reference type,
>> but the operator_arrow_result stuff is trying to do something more
>> complicated. In what case is the operator_arrow_proxy useful? Is there
>> some way to get what I want using iterator_facade?
> <snip>
>> BTW I have been testing with an oldish version of Boost, but I've looked
>> at the source in svn and it doesn't seem to have changed much.
>>
>>
>> Cheers, Phil.
>>
>
> (Also looking at the code) operator_array_proxy should be probably be
> instantiated with the Reference, not ValueType...??? Would that be
> correct? I.e., operator_array_proxy should wrap a reference (which is
> not a real C++ reference), not a value...
>
> You *could* just overload operator-> in the derived class to do
> something else (in this case, I would say try using a proxy that wraps a
> reference).
>
> Also, just to be clear, the operator_array_proxy stuff in
> iterator_facade fails not because std::pair< const KEY, VALUE& > isn't
> convertible to std::pair< KEY, VALUE >, but because their pointers
> aren't convertible. At least that's what I'm seeing...
>
> Seems like I stumbled on this in the past and rather than figure out
> what was wrong, I just redefined operator-> in the derived class to work...
Hi Jeff,
s/operator_array_proxy/operator_arrow_proxy/g
There seem to be a couple of issues here. Firstly, as you say
operator_arrow_proxy is being instantiated with the ValueType but there
would be more chance of it working if it were instantiated with the Reference.
Secondly, std::pair containing a non-const reference for the value
causes a "forming reference to reference" error in
is_convertible<pair<KEY,VALUE&>,pair<KEY,VALUE>>
(is_convertible_basic_impl gcc version; is_convertible.hpp line 137).
Is this a SFINAE issue? This is being called from
iterator_facade_default_category "check for readability". I'm out of
my depth trying to track this down any further.
I have fixed it, presumably as you did, with a custom pair-like type
and a custom arrow_proxy type, something like this:
struct iter_ref_t { // replacement for std::pair
const KEY first;
VALUE& second;
iter_ref_t(const KEY first_, VALUE& second_): first(first_),
second(second_) {}
};
class iterator:
public boost::iterator_facade<iterator,
std::pair<KEY,VALUE>,
boost::bidirectional_traversal_tag,
iter_ref_t>
{
iter_ref_t dereference() const { return iter_ref_t(....); }
struct arrow_proxy { // replacement for iterator_facade::operator_arrow_proxy
mutable iter_ref_t r;
arrow_proxy(const iter_ref_t& r_): r(r_) {}
iter_ref_t* operator->() const { return &r; }
};
public:
arrow_proxy operator->() const { // override version in iterator_facade
return arrow_proxy(dereference());
}
};
Would any Boost.Iterator experts care to comment?
BTW it seems to me that the operator_arrow_proxy thing is really a sort
of "smart pointer" - it's an object that looks like a pointer, but it
always points to an object that it contains. Does it have more general applications?
Regards, Phil.