/* * Copyright (c) 2017 Jaroslav Jindrak * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LIBCPP_UTILITY #define LIBCPP_UTILITY #include #include #include namespace std { /** * 20.2.1, operators: */ namespace rel_ops { template bool operator!=(const T& lhs, const T& rhs) { return !(lhs == rhs); } template bool operator>(const T& lhs, const T& rhs) { return (rhs < lhs); } template bool operator<=(const T& lhs, const T& rhs) { return !(rhs < lhs); } template bool operator>=(const T& lhs, const T& rhs) { return !(lhs < rhs); } } /** * 20.2.4, forward/move helpers: */ template constexpr T&& forward(remove_reference_t& t) noexcept { return static_cast(t); } template constexpr T&& forward(remove_reference_t&& t) noexcept { return static_cast(t); } template constexpr remove_reference_t&& move(T&& t) noexcept { return static_cast&&>(t); } /** * 20.2.2, swap: */ template void swap(T& x, T& y) /* noexcept(is_nothrow_move_constructible::value && */ /* is_nothrow_move_assignable::value) */ { T tmp{move(x)}; x = move(y); y = move(tmp); } template void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b))) { // TODO: Use swap_ranges(a, a + N, b); when implemented. } /** * 20.2.3, exchange: */ template T exchange(T& obj, U&& new_val) { T old_val = move(obj); obj = forward(new_val); return old_val; } /** * 20.2.5, function template declval: * Note: This function only needs declaration, not * implementation. */ template add_rvalue_reference_t declval() noexcept; /** * 20.3, pairs: */ struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; template struct pair { using first_type = T1; using second_type = T2; T1 first; T2 second; pair(const pair&) = default; pair(pair&&) = default; constexpr pair() : first{}, second{} { /* DUMMY BODY */ } constexpr pair(const T1& x, const T2& y) : first{x}, second{y} { /* DUMMY BODY */ } template constexpr pair(U&& x, V&& y) : first(x), second(y) { /* DUMMY BODY */ } template constexpr pair(const pair& other) : first(other.first), second(other.second) { /* DUMMY BODY */ } template constexpr pair(pair&& other) : first(forward(other.first)), second(forward(other.second)) { /* DUMMY BODY */ } /* TODO: need tuple, piecewise_construct_t template pair(piecewise_construct_t, tuple first_args, tuple second_args) { // TODO: } */ pair& operator=(const pair& other) { first = other.first; second = other.second; return *this; } template pair& operator=(const pair& other) { first = other.first; second = other.second; return *this; } pair& operator=(pair&& other) noexcept { first = forward(other.first); second = forward(other.second); return *this; } }; /** * 20.3.3, specialized algorithms: */ template constexpr bool operator==(const pair& lhs, const pair& rhs) { return lhs.first == rhs.first && lhs.second == rhs.second; } template constexpr bool operator<(const pair& lhs, const pair& rhs) { return lhs.first < rhs.first || (!(rhs.first < lhs.first) && lhs.second < rhs.second); } template constexpr bool operator!=(const pair& lhs, const pair& rhs) { return !(lhs == rhs); } template constexpr bool operator>(const pair& lhs, const pair& rhs) { return rhs < lhs; } template constexpr bool operator>=(const pair& lhs, const pair& rhs) { return !(lhs < rhs); } template constexpr bool operator<=(const pair& lhs, const pair& rhs) { return !(rhs < lhs); } template constexpr void swap(pair& lhs, pair& rhs) noexcept(noexcept(lhs.swap(rhs))) { lhs.swap(rhs); } template constexpr auto make_pair(T1&& t1, T2&& t2) { return pair< aux::transform_tuple_types_t, aux::transform_tuple_types_t >{ forward(t1), forward(t2) }; } /** * 20.3.4, tuple-like access to pair: */ template struct tuple_size; template struct tuple_size> : integral_constant { /* DUMMY BODY */ }; template struct tuple_element; template struct tuple_element<0, pair> : aux::type_is { /* DUMMY BODY */ }; template struct tuple_element<1, pair> : aux::type_is { /* DUMMY BODY */ }; template using tuple_element_t = typename tuple_element::type; template constexpr tuple_element_t>& get(pair& p) noexcept { if constexpr (I == 0) return p.first; else return p.second; } template constexpr const tuple_element_t>& get(const pair& p) noexcept { if constexpr (I == 0) return p.first; else return p.second; } template constexpr tuple_element_t>&& get(pair&& p) noexcept { if constexpr (I == 0) return forward(p.first); else return forward(p.second); } template constexpr T& get(pair& p) noexcept { static_assert(!is_same_v, "get(pair) requires distinct types"); return get<0>(p); } template constexpr const T& get(const pair& p) noexcept { static_assert(!is_same_v, "get(pair) requires distinct types"); return get<0>(p); } template constexpr T&& get(pair&& p) noexcept { static_assert(!is_same_v, "get(pair) requires distinct types"); return get<0>(move(p)); } template constexpr T& get(pair& p) noexcept { static_assert(!is_same_v, "get(pair) requires distinct types"); return get<1>(p); } template constexpr const T& get(const pair& p) noexcept { static_assert(!is_same_v, "get(pair) requires distinct types"); return get<1>(p); } template constexpr T&& get(pair&& p) noexcept { static_assert(!is_same_v, "get(pair) requires distinct types"); return get<1>(move(p)); } /** * 20.5.2, class template integer_sequence: */ template struct integer_sequence { using value_type = T; static constexpr size_t size() noexcept { return sizeof...(Is); } using next = integer_sequence; }; template using index_sequence = integer_sequence; /** * 20.5.3, alias template make_integer_sequence: */ namespace aux { template struct make_integer_sequence { /** * Recursive to the bottom case below, appends sizeof...(Is) in * every next "call", building the sequence. */ using type = typename make_integer_sequence::type::next; }; template struct make_integer_sequence { using type = integer_sequence; }; } /** * Problem: We can't specialize the N parameter because it is a value parameter * depending on a type parameter. * Solution: According to the standard: if N is negative, the program is ill-formed, * so we just recast it to uintmax_t :) */ template using make_integer_sequence = typename aux::make_integer_sequence::type; template using make_index_sequence = make_integer_sequence; } #endif