Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:25:46

0001 /*  This file is part of the Vc library. {{{
0002 Copyright © 2016 Matthias Kretz <kretz@kde.org>
0003 
0004 Redistribution and use in source and binary forms, with or without
0005 modification, are permitted provided that the following conditions are met:
0006     * Redistributions of source code must retain the above copyright
0007       notice, this list of conditions and the following disclaimer.
0008     * Redistributions in binary form must reproduce the above copyright
0009       notice, this list of conditions and the following disclaimer in the
0010       documentation and/or other materials provided with the distribution.
0011     * Neither the names of contributing organizations nor the
0012       names of its contributors may be used to endorse or promote products
0013       derived from this software without specific prior written permission.
0014 
0015 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
0016 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0017 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0018 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
0019 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0020 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0021 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0022 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025 
0026 }}}*/
0027 
0028 #ifndef VC_COMMON_ELEMENTREFERENCE_H_
0029 #define VC_COMMON_ELEMENTREFERENCE_H_
0030 
0031 #include "macros.h"
0032 
0033 namespace Vc_VERSIONED_NAMESPACE
0034 {
0035 namespace Detail
0036 {
0037 template <typename U, typename Accessor = U> class ElementReference
0038 {
0039     friend U;
0040     friend Accessor;
0041     Vc_INTRINSIC ElementReference(U &o, int i) noexcept : index(i), obj(o) {}
0042 
0043     static constexpr bool get_noexcept =
0044         noexcept(Accessor::get(std::declval<U &>(), int()));
0045     template <typename T> static constexpr bool set_noexcept()
0046     {
0047         return noexcept(Accessor::set(std::declval<U &>(), int(), std::declval<T>()));
0048     }
0049 
0050 public:
0051     using value_type = typename U::value_type;
0052     Vc_INTRINSIC ElementReference(const ElementReference &) = delete;
0053 
0054     /**
0055      * Move Constructor
0056      *
0057      * this is the only way to constructor an ElementReference in user code
0058      *
0059      * \note
0060      * Please be aware that this class models the concept of a reference
0061      * and as such it can have the same lifetime issue as a standard C++
0062      * reference.
0063      *
0064      * \note
0065      * C++ 17 support copy-elision, which in turn allows to
0066      * the ElementReference obtained via operator[] from a function
0067      * and avoid copying. C++11 and C++14 don't offer this, thus we add
0068      * the move constructor, to allow them to move the data and thus avoid
0069      * copying (which was prohibited by the deleted constructor above
0070      */
0071     Vc_INTRINSIC ElementReference(ElementReference &&) = default;
0072 
0073     Vc_INTRINSIC operator value_type() const noexcept(get_noexcept)
0074     {
0075         return Accessor::get(obj, index);
0076     }
0077 
0078     template <typename T>
0079         Vc_INTRINSIC ElementReference &operator=(T &&x) &&
0080         noexcept(noexcept(Accessor::set(std::declval<U &>(), int(), std::declval<T>())))
0081     {
0082         Accessor::set(obj, index, std::forward<T>(x));
0083         return *this;
0084     }
0085 
0086 // TODO: improve with operator.()
0087 
0088 #define Vc_OP_(op_)                                                                      \
0089     template <typename T, typename R = decltype(std::declval<const value_type &>()       \
0090                                                     op_ std::declval<T>())>              \
0091         Vc_INTRINSIC ElementReference &operator op_##=(T &&x) &&                         \
0092         noexcept(get_noexcept && noexcept(Accessor::set(std::declval<U &>(), int(),      \
0093                                                         std::declval<R &&>())))          \
0094     {                                                                                    \
0095         const value_type &lhs = Accessor::get(obj, index);                               \
0096         Accessor::set(obj, index, lhs op_ std::forward<T>(x));                           \
0097         return *this;                                                                    \
0098     }
0099     Vc_ALL_ARITHMETICS(Vc_OP_);
0100     Vc_ALL_SHIFTS(Vc_OP_);
0101     Vc_ALL_BINARY(Vc_OP_);
0102 #undef Vc_OP_
0103 
0104     template <typename = void>
0105         Vc_INTRINSIC ElementReference &operator++() &&
0106         noexcept(noexcept(std::declval<value_type &>() =
0107                               Accessor::get(std::declval<U &>(), int())) &&
0108                  set_noexcept<decltype(++std::declval<value_type &>())>())
0109     {
0110         value_type x = Accessor::get(obj, index);
0111         Accessor::set(obj, index, ++x);
0112         return *this;
0113     }
0114 
0115     template <typename = void>
0116         Vc_INTRINSIC value_type operator++(int) &&
0117         noexcept(noexcept(std::declval<value_type &>() =
0118                               Accessor::get(std::declval<U &>(), int())) &&
0119                  set_noexcept<decltype(std::declval<value_type &>()++)>())
0120     {
0121         const value_type r = Accessor::get(obj, index);
0122         value_type x = r;
0123         Accessor::set(obj, index, ++x);
0124         return r;
0125     }
0126 
0127     template <typename = void>
0128         Vc_INTRINSIC ElementReference &operator--() &&
0129         noexcept(noexcept(std::declval<value_type &>() =
0130                               Accessor::get(std::declval<U &>(), int())) &&
0131                  set_noexcept<decltype(--std::declval<value_type &>())>())
0132     {
0133         value_type x = Accessor::get(obj, index);
0134         Accessor::set(obj, index, --x);
0135         return *this;
0136     }
0137 
0138     template <typename = void>
0139         Vc_INTRINSIC value_type operator--(int) &&
0140         noexcept(noexcept(std::declval<value_type &>() =
0141                               Accessor::get(std::declval<U &>(), int())) &&
0142                  set_noexcept<decltype(std::declval<value_type &>()--)>())
0143     {
0144         const value_type r = Accessor::get(obj, index);
0145         value_type x = r;
0146         Accessor::set(obj, index, --x);
0147         return r;
0148     }
0149 
0150     friend void swap(ElementReference &&a, ElementReference &&b) {
0151         value_type tmp(a);
0152         static_cast<ElementReference &&>(a) = static_cast<value_type>(b);
0153         static_cast<ElementReference &&>(b) = tmp;
0154     }
0155 
0156     friend void swap(value_type &a, ElementReference &&b) {
0157         value_type tmp(a);
0158         a = static_cast<value_type>(b);
0159         static_cast<ElementReference &&>(b) = tmp;
0160     }
0161 
0162     friend void swap(ElementReference &&a, value_type &b) {
0163         value_type tmp(a);
0164         static_cast<ElementReference &&>(a) = b;
0165         b = tmp;
0166     }
0167 
0168 private:
0169     int index;
0170     U &obj;
0171 };
0172 
0173 }  // namespace Detail
0174 }  // namespace Vc
0175 
0176 #endif  // VC_COMMON_ELEMENTREFERENCE_H_
0177 
0178 // vim: foldmethod=marker