/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License Version 2.0 with LLVM Exceptions * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * https://llvm.org/LICENSE.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include namespace unifex { template extern bool const is_swappable_with_v; template extern bool const is_nothrow_swappable_with_v; namespace _swap { void swap(); template decltype(static_cast(swap(UNIFEX_DECLVAL(T&&), UNIFEX_DECLVAL(U&&))), std::true_type{}) _try_adl_swap(int); template std::false_type _try_adl_swap(long); template inline constexpr bool is_adl_swappable_v = decltype(_swap::_try_adl_swap(0))::value; struct _fn { // Dispatch to user-defined swap found via ADL: UNIFEX_TEMPLATE(typename T, typename U) (requires is_adl_swappable_v) constexpr void operator()(T &&t, U &&u) const noexcept(noexcept(swap((T &&) t, (U &&) u))) { swap((T &&) t, (U &&) u); } // For intrinsically swappable (i.e., movable) types for which // a swap overload cannot be found via ADL, swap by moving. UNIFEX_TEMPLATE(typename T) (requires (!is_adl_swappable_v)) constexpr auto operator()(T &a, T &b) const noexcept(noexcept(a = T(static_cast(b)))) -> decltype(static_cast(a = T(static_cast(b)))) { T tmp = static_cast(a); a = static_cast(b); b = static_cast(tmp); } // For arrays of intrinsically swappable (i.e., movable) types // for which a swap overload cannot be found via ADL, swap array // elements by moving. UNIFEX_TEMPLATE(typename T, typename U, std::size_t N) (requires (!is_adl_swappable_v) && is_swappable_with_v) constexpr void operator()(T (&t)[N], U (&u)[N]) const noexcept(is_nothrow_swappable_with_v) { for(std::size_t i = 0; i < N; ++i) (*this)(t[i], u[i]); } }; } // namespace _swap namespace _swap_cpo { inline constexpr _swap::_fn swap {}; } // namespace _swap_cpo using namespace _swap_cpo; template inline constexpr bool is_swappable_with_v = false; template inline constexpr bool is_swappable_with_v< T, U, decltype(unifex::swap(UNIFEX_DECLVAL(T&&), UNIFEX_DECLVAL(U&&)))> = true; template inline constexpr bool is_nothrow_swappable_with_v = false; template inline constexpr bool is_nothrow_swappable_with_v< T, U, decltype(unifex::swap(UNIFEX_DECLVAL(T&&), UNIFEX_DECLVAL(U&&)))> = noexcept(swap(UNIFEX_DECLVAL(T&&), UNIFEX_DECLVAL(U&&))); } // namespace unifex #include