Turi Create  4.0
function_output_iterator.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 // (C) Copyright Jeremy Siek 2001.
7 // Distributed under the Boost Software License, Version 1.0. (See
8 // accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 
11 // Revision History:
12 
13 // 27 Feb 2001 Jeremy Siek
14 // Initial checkin.
15 
16 #ifndef TURI_FUNCTION_OUTPUT_ITERATOR_HPP
17 #define TURI_FUNCTION_OUTPUT_ITERATOR_HPP
18 
19 #include <iterator>
20 
21 namespace turi {
22 
23  /**
24  * \ingroup util
25  * Copied and amended from boost.
26  * Applies a function to an iterator, outputing an iterator.
27  */
28  template <class UnaryFunction, class MoveFunction>
30  typedef function_output_iterator self;
31  public:
32  typedef std::output_iterator_tag iterator_category;
33  typedef void value_type;
34  typedef void difference_type;
35  typedef void pointer;
36  typedef void reference;
37 
38  explicit function_output_iterator() {}
39 
40  explicit function_output_iterator(const UnaryFunction& f, const MoveFunction& f2)
41  : m_f(f), m_f2(f2) {}
42 
43  struct output_proxy {
44  output_proxy(UnaryFunction& f, MoveFunction& f2) : m_f(f), m_f2(f2) { }
45  template <class T> output_proxy& operator=(const T& value) {
46  m_f(value);
47  return *this;
48  }
49 
50 
51  template <typename T>
52  void output_forward(T&& value, std::integral_constant<bool, true>) {
53  // value is an rvalue
54  m_f2(std::move(value));
55  }
56 
57  template <typename T>
58  void output_forward(T&& value, std::integral_constant<bool, false>) {
59  // value is an lvalue
60  m_f(value);
61  }
62 
63  template <class T> output_proxy& operator=(T&& value) {
64  // annoying T&& is a universal reference.
65  // So redispatch with a check for r-value-referenceness
66  // and call the move version or the const ref version as required
67  output_forward(std::forward<T>(value),
68  typename std::is_rvalue_reference<decltype(std::forward<T>(value))>::type());
69  return *this;
70  }
71 
72  template <class T> output_proxy& operator=(const T&& value) {
73  // overload for const T condition. in which case we call the
74  // const T& version
75  output_forward(value, std::integral_constant<bool, false>());
76  return *this;
77  }
78 
79 
80  UnaryFunction& m_f;
81  MoveFunction& m_f2;
82  };
83  output_proxy operator*() { return output_proxy(m_f, m_f2); }
84  self& operator++() { return *this; }
85  self& operator++(int) { return *this; }
86  private:
87  UnaryFunction m_f;
88  MoveFunction m_f2;
89  };
90 } // namespace boost
91 
92 #endif // BOOST_FUNCTION_OUTPUT_ITERATOR_HPP