1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
// Copyright (C) 2022 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/stl_interfaces/iterator_interface.hpp>
#include <type_traits>
#include <utility>
struct node
{
using value_type = std::pair<int, int>;
value_type kv_;
node * next_;
};
template<typename Node>
struct iterator
: boost::stl_interfaces::iterator_interface<
#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
iterator<Node>,
#endif
std::forward_iterator_tag, Node>
{
using value_type = typename Node::value_type;
constexpr iterator() noexcept = default;
constexpr explicit iterator(Node * it) : it_{it} {}
template<
typename Node2,
typename Enable = std::enable_if_t<
std::is_convertible<Node2 *, Node *>{} && !std::is_const<Node2>{} &&
std::is_const<Node>{}>>
constexpr iterator(iterator<Node2> other) noexcept : it_{other.it_}
{}
constexpr value_type const & operator*() const noexcept { return it_->kv_; }
template<
typename T = Node,
typename std::enable_if_t<!std::is_const<T>{}, bool> = true>
constexpr value_type & operator*() noexcept
{
return it_->kv_;
}
constexpr iterator & operator++() noexcept
{
it_ = it_->next_;
return *this;
}
using base_type = boost::stl_interfaces::
iterator_interface<iterator<Node>, std::forward_iterator_tag, Node>;
using base_type::operator++;
friend constexpr bool operator==(iterator lhs, iterator rhs) noexcept
{
return lhs.it_ == rhs.it_;
}
private:
Node * it_;
template<typename Node2>
friend struct iterator;
};
void compile_sfinae_path_mutable_iterator()
{
auto it = iterator<node>{};
if ((*it).first == 42) {
(*it).second = 13;
}
}
|