295 lines
8.7 KiB
C++
295 lines
8.7 KiB
C++
/*
|
|
* 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 <unifex/detail/concept_macros.hpp>
|
|
#include <unifex/swap.hpp>
|
|
#include <unifex/type_traits.hpp>
|
|
|
|
#include <functional>
|
|
#include <type_traits>
|
|
|
|
#include <unifex/detail/prologue.hpp>
|
|
|
|
namespace unifex {
|
|
|
|
template <typename A, typename B>
|
|
UNIFEX_CONCEPT
|
|
same_as =
|
|
UNIFEX_IS_SAME(A, B) &&
|
|
UNIFEX_IS_SAME(B, A);
|
|
|
|
template <typename From, typename To>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_explicitly_convertible_to,
|
|
requires(From(*from)()) //
|
|
(
|
|
static_cast<To>(from())
|
|
));
|
|
template <typename From, typename To>
|
|
UNIFEX_CONCEPT
|
|
convertible_to =
|
|
std::is_convertible_v<std::add_rvalue_reference_t<From>, To> &&
|
|
UNIFEX_FRAGMENT(unifex::_explicitly_convertible_to, From, To);
|
|
|
|
/// \cond
|
|
namespace detail {
|
|
template <typename T>
|
|
using _cref_t = std::remove_reference_t<T> const &;
|
|
|
|
template <class T>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_boolean_testable_impl,
|
|
requires(T && t)
|
|
(
|
|
requires(convertible_to<decltype(! (T &&) t), bool>)
|
|
));
|
|
template <class T>
|
|
UNIFEX_CONCEPT
|
|
_boolean_testable =
|
|
UNIFEX_FRAGMENT(_boolean_testable_impl, T) &&
|
|
convertible_to<T, bool>;
|
|
|
|
UNIFEX_DIAGNOSTIC_PUSH
|
|
UNIFEX_DIAGNOSTIC_IGNORE_FLOAT_EQUAL
|
|
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_weakly_equality_comparable_with,
|
|
requires(_cref_t<T> t, _cref_t<U> u) //
|
|
(
|
|
requires(_boolean_testable<decltype(t == u)>),
|
|
requires(_boolean_testable<decltype(t != u)>),
|
|
requires(_boolean_testable<decltype(u == t)>),
|
|
requires(_boolean_testable<decltype(u != t)>)
|
|
));
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT
|
|
weakly_equality_comparable_with_ =
|
|
UNIFEX_FRAGMENT(detail::_weakly_equality_comparable_with, T, U);
|
|
|
|
UNIFEX_DIAGNOSTIC_POP
|
|
} // namespace detail
|
|
/// \endcond
|
|
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_derived_from,
|
|
requires()(0) &&
|
|
convertible_to<T const volatile *, U const volatile *>);
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT
|
|
derived_from =
|
|
UNIFEX_IS_BASE_OF(U, T) &&
|
|
UNIFEX_FRAGMENT(unifex::_derived_from, T, U);
|
|
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_assignable_from,
|
|
requires(T t, U && u) //
|
|
(
|
|
t = (U &&) u,
|
|
requires(same_as<T, decltype(t = (U &&) u)>)
|
|
));
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT
|
|
assignable_from =
|
|
std::is_lvalue_reference_v<T> &&
|
|
UNIFEX_FRAGMENT(unifex::_assignable_from, T, U);
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_swappable,
|
|
requires(T & t, T & u) //
|
|
(
|
|
unifex::swap(t, u)
|
|
));
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
swappable =
|
|
UNIFEX_FRAGMENT(unifex::_swappable, T);
|
|
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_swappable_with,
|
|
requires(T && t, U && u) //
|
|
(
|
|
unifex::swap((T &&) t, (T &&) t),
|
|
unifex::swap((U &&) u, (U &&) u),
|
|
unifex::swap((U &&) u, (T &&) t),
|
|
unifex::swap((T &&) t, (U &&) u)
|
|
));
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT
|
|
swappable_with =
|
|
//common_reference_with<detail::_cref_t<T>, detail::_cref_t<U>> &&
|
|
UNIFEX_FRAGMENT(unifex::_swappable_with, T, U);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Comparison concepts
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
equality_comparable =
|
|
detail::weakly_equality_comparable_with_<T, T>;
|
|
|
|
// template <typename T, typename U>
|
|
// UNIFEX_CONCEPT_FRAGMENT(
|
|
// _equality_comparable_with,
|
|
// requires()(0) &&
|
|
// equality_comparable<
|
|
// common_reference_t<detail::_cref_t<T>, detail::_cref_t<U>>>);
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT
|
|
equality_comparable_with =
|
|
equality_comparable<T> &&
|
|
equality_comparable<U> &&
|
|
detail::weakly_equality_comparable_with_<T, U>;// &&
|
|
//common_reference_with<detail::_cref_t<T>, detail::_cref_t<U>> &&
|
|
//UNIFEX_FRAGMENT(unifex::_equality_comparable_with, T, U);
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_totally_ordered,
|
|
requires(detail::_cref_t<T> t, detail::_cref_t<T> u) //
|
|
(
|
|
requires(detail::_boolean_testable<decltype(t < u)>),
|
|
requires(detail::_boolean_testable<decltype(t > u)>),
|
|
requires(detail::_boolean_testable<decltype(u <= t)>),
|
|
requires(detail::_boolean_testable<decltype(u >= t)>)
|
|
));
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
totally_ordered =
|
|
equality_comparable<T> &&
|
|
UNIFEX_FRAGMENT(unifex::_totally_ordered, T);
|
|
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_totally_ordered_with,
|
|
requires(detail::_cref_t<T> t, detail::_cref_t<U> u) //
|
|
(
|
|
requires(detail::_boolean_testable<decltype(t < u)>),
|
|
requires(detail::_boolean_testable<decltype(t > u)>),
|
|
requires(detail::_boolean_testable<decltype(t <= u)>),
|
|
requires(detail::_boolean_testable<decltype(t >= u)>),
|
|
requires(detail::_boolean_testable<decltype(u < t)>),
|
|
requires(detail::_boolean_testable<decltype(u > t)>),
|
|
requires(detail::_boolean_testable<decltype(u <= t)>),
|
|
requires(detail::_boolean_testable<decltype(u >= t)>)
|
|
));
|
|
//&& totally_ordered<
|
|
// common_reference_t<detail::_cref_t<T>, detail::_cref_t<U>>>
|
|
template <typename T, typename U>
|
|
UNIFEX_CONCEPT
|
|
totally_ordered_with =
|
|
totally_ordered<T> &&
|
|
totally_ordered<U> &&
|
|
equality_comparable_with<T, U> &&
|
|
//common_reference_with<detail::_cref_t<T>, detail::_cref_t<U>> &&
|
|
UNIFEX_FRAGMENT(unifex::_totally_ordered_with, T, U);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Object concepts
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
destructible =
|
|
std::is_nothrow_destructible_v<T>;
|
|
|
|
template <typename T, typename... Args>
|
|
UNIFEX_CONCEPT
|
|
constructible_from =
|
|
destructible<T> &&
|
|
UNIFEX_IS_CONSTRUCTIBLE(T, Args...);
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
default_constructible =
|
|
constructible_from<T>;
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
move_constructible =
|
|
constructible_from<T, T> &&
|
|
convertible_to<T, T>;
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_copy_constructible,
|
|
requires()(0) &&
|
|
constructible_from<T, T &> &&
|
|
constructible_from<T, T const &> &&
|
|
constructible_from<T, T const> &&
|
|
convertible_to<T &, T> &&
|
|
convertible_to<T const &, T> &&
|
|
convertible_to<T const, T>);
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
copy_constructible =
|
|
move_constructible<T> &&
|
|
UNIFEX_FRAGMENT(unifex::_copy_constructible, T);
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_move_assignable,
|
|
requires()(0) &&
|
|
assignable_from<T &, T>);
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
movable =
|
|
std::is_object_v<T> &&
|
|
move_constructible<T> &&
|
|
UNIFEX_FRAGMENT(unifex::_move_assignable, T) &&
|
|
swappable<T>;
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT_FRAGMENT(
|
|
_copy_assignable,
|
|
requires()(0) &&
|
|
assignable_from<T &, T const &>);
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
copyable =
|
|
copy_constructible<T> &&
|
|
movable<T> &&
|
|
UNIFEX_FRAGMENT(unifex::_copy_assignable, T);
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
semiregular =
|
|
copyable<T> &&
|
|
default_constructible<T>;
|
|
// Axiom: copies are independent. See Fundamentals of Generic Programming
|
|
// http://www.stepanovpapers.com/DeSt98.pdf
|
|
|
|
template <typename T>
|
|
UNIFEX_CONCEPT
|
|
regular =
|
|
semiregular<T> &&
|
|
equality_comparable<T>;
|
|
|
|
template <typename Fn, typename... As>
|
|
UNIFEX_CONCEPT //
|
|
invocable = //
|
|
std::is_invocable_v<Fn, As...>;
|
|
|
|
} // namespace unifex
|
|
|
|
#include <unifex/detail/epilogue.hpp>
|