On Monday, January 21, 2019 at 1:26:03 AM UTC-5, Paavo Helde wrote:
> On 21.01.2019 6:35, Daniel wrote:
> > Given an iterator over std::pair<T1,T2>, and wishing to adapt it to an
> > iterator over
> >
> > template <class T1,class T2>
> > struct key_value
> > {
> > T1 key;
> > T2 value;
> > };
>
> Iterator is over something like std::map or std::vector, not over
> std::pair,
Over the elements in an associative map of type std::pair<const T1,T2>, or
over the elements in a container of any sort where they come as
std::pair<T1,T2> or std::pair<const T1,T2>. I'm sorry if that wasn't
obvious.
> > is there anything terribly wrong with
> >
> > template <class Iter>
> > class iterator_adapter
> > {
> > Iter it;
> > public:
> > typedef std::input_iterator_tag iterator_category;
> > typedef typename std::iterator_traits<Iter>::value_type::first_type T1;
> > typedef typename std::iterator_traits<Iter>::value_type::second_type T2;
> > typedef key_value<T1,T2> value_type;
> > typedef value_type reference; // (*)
> >
> > reference operator*() { return key_value(it->first,it->second); }
>
> As written, this is not an iterator as it is lacking an increment
> operation (would be easy to add though).
I'm sorry if it wasn't obvious that I'm highlighting the typedef of the
reference in the context of a LegacyInputIterator. My apologies.
> Also, the 'reference' type is not a reference, misleading the user.
I'm sure you're aware that boost many times uses
#typedef value_type reference;
in other contexts for technical reasons. And misleading in what sense?
There are actually a fair number of places in boost where X::reference does
not equate to &X::value_type, for technical reasons. For what reason
would a user expect that? A user is right to expect member types to have
properties that satisfy the requirements of the language, but no more.
My question was about whether the line (*) above violated any formal
properties of a LegacyInputIterator.
> This also means that this adaptor can only be used as InputIterator,
I included the LegacyInputIterator tag in my fragment to frame that as the
context.
> My question is what's the point? Basically what you have written here
> just converts a std::pair to key_value. Why do you want this to happen
> inside an iterator?
> I would iterate over the collection normally and
> just convert the elements inside the loop as needed.
Taken literally, I don't think that makes sense, as a user
wouldn't have access to the implementation details of a class
in another library that takes a pair of iterators over key_value<T1,T2>'s
in a constructor, or an insert statement. Typically that's the context
when you require an adapter, when you have one thing, and need another.
I apologize if that wasn't obvious.
Perhaps you're suggesting that the class in the other library should
support, say,
template<class InputIt, class Convert>
void insert(InputIt first, InputIt last, Convert convert)
{
and allow, perhaps
j.insert(items.begin(), items.end(),
[](const std::pair<const T1,T2>& p){return
key_value<T1,T2>(p.first,p.second);});
Thanks,
Daniel