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

source code of boost/libs/stl_interfaces/test/compile_sfinae_path_mutable_iterator.cpp