Vc 1.4.5
SIMD Vector Classes for C++
 
Loading...
Searching...
No Matches
elementreference.h
1/* This file is part of the Vc library. {{{
2Copyright © 2016 Matthias Kretz <kretz@kde.org>
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the names of contributing organizations nor the
12 names of its contributors may be used to endorse or promote products
13 derived from this software without specific prior written permission.
14
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26}}}*/
27
28#ifndef VC_COMMON_ELEMENTREFERENCE_H_
29#define VC_COMMON_ELEMENTREFERENCE_H_
30
31#include "macros.h"
32
33namespace Vc_VERSIONED_NAMESPACE
34{
35namespace Detail
36{
37template <typename U, typename Accessor = U> class ElementReference
38{
39 friend U;
40 friend Accessor;
41 Vc_INTRINSIC ElementReference(U &o, int i) noexcept : index(i), obj(o) {}
42
43 static constexpr bool get_noexcept =
44 noexcept(Accessor::get(std::declval<U &>(), int()));
45 template <typename T> static constexpr bool set_noexcept()
46 {
47 return noexcept(Accessor::set(std::declval<U &>(), int(), std::declval<T>()));
48 }
49
50public:
51 using value_type = typename U::value_type;
52 Vc_INTRINSIC ElementReference(const ElementReference &) = delete;
53
71 Vc_INTRINSIC ElementReference(ElementReference &&) = default;
72
73 Vc_INTRINSIC operator value_type() const noexcept(get_noexcept)
74 {
75 return Accessor::get(obj, index);
76 }
77
78 template <typename T>
79 Vc_INTRINSIC ElementReference &operator=(T &&x) &&
80 noexcept(noexcept(Accessor::set(std::declval<U &>(), int(), std::declval<T>())))
81 {
82 Accessor::set(obj, index, std::forward<T>(x));
83 return *this;
84 }
85
86// TODO: improve with operator.()
87
88#define Vc_OP_(op_) \
89 template <typename T, typename R = decltype(std::declval<const value_type &>() \
90 op_ std::declval<T>())> \
91 Vc_INTRINSIC ElementReference &operator op_##=(T &&x) && \
92 noexcept(get_noexcept && noexcept(Accessor::set(std::declval<U &>(), int(), \
93 std::declval<R &&>()))) \
94 { \
95 const value_type &lhs = Accessor::get(obj, index); \
96 Accessor::set(obj, index, lhs op_ std::forward<T>(x)); \
97 return *this; \
98 }
99 Vc_ALL_ARITHMETICS(Vc_OP_);
100 Vc_ALL_SHIFTS(Vc_OP_);
101 Vc_ALL_BINARY(Vc_OP_);
102#undef Vc_OP_
103
104 template <typename = void>
105 Vc_INTRINSIC ElementReference &operator++() &&
106 noexcept(noexcept(std::declval<value_type &>() =
107 Accessor::get(std::declval<U &>(), int())) &&
108 set_noexcept<decltype(++std::declval<value_type &>())>())
109 {
110 value_type x = Accessor::get(obj, index);
111 Accessor::set(obj, index, ++x);
112 return *this;
113 }
114
115 template <typename = void>
116 Vc_INTRINSIC value_type operator++(int) &&
117 noexcept(noexcept(std::declval<value_type &>() =
118 Accessor::get(std::declval<U &>(), int())) &&
119 set_noexcept<decltype(std::declval<value_type &>()++)>())
120 {
121 const value_type r = Accessor::get(obj, index);
122 value_type x = r;
123 Accessor::set(obj, index, ++x);
124 return r;
125 }
126
127 template <typename = void>
128 Vc_INTRINSIC ElementReference &operator--() &&
129 noexcept(noexcept(std::declval<value_type &>() =
130 Accessor::get(std::declval<U &>(), int())) &&
131 set_noexcept<decltype(--std::declval<value_type &>())>())
132 {
133 value_type x = Accessor::get(obj, index);
134 Accessor::set(obj, index, --x);
135 return *this;
136 }
137
138 template <typename = void>
139 Vc_INTRINSIC value_type operator--(int) &&
140 noexcept(noexcept(std::declval<value_type &>() =
141 Accessor::get(std::declval<U &>(), int())) &&
142 set_noexcept<decltype(std::declval<value_type &>()--)>())
143 {
144 const value_type r = Accessor::get(obj, index);
145 value_type x = r;
146 Accessor::set(obj, index, --x);
147 return r;
148 }
149
150 friend void swap(ElementReference &&a, ElementReference &&b) {
151 value_type tmp(a);
152 static_cast<ElementReference &&>(a) = static_cast<value_type>(b);
153 static_cast<ElementReference &&>(b) = tmp;
154 }
155
156 friend void swap(value_type &a, ElementReference &&b) {
157 value_type tmp(a);
158 a = static_cast<value_type>(b);
159 static_cast<ElementReference &&>(b) = tmp;
160 }
161
162 friend void swap(ElementReference &&a, value_type &b) {
163 value_type tmp(a);
164 static_cast<ElementReference &&>(a) = b;
165 b = tmp;
166 }
167
168private:
169 int index;
170 U &obj;
171};
172
173} // namespace Detail
174} // namespace Vc
175
176#endif // VC_COMMON_ELEMENTREFERENCE_H_
177
178// vim: foldmethod=marker