147 lines
5.7 KiB
C++
147 lines
5.7 KiB
C++
// Copyright 2021 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// 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.
|
|
|
|
// Copyright 2019 The Fuchsia Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#pragma once
|
|
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
namespace android::base {
|
|
namespace fit {
|
|
namespace internal {
|
|
|
|
// Utility to return the first type in a parameter pack.
|
|
template <typename... Ts>
|
|
struct First;
|
|
template <typename FirstType, typename... Rest>
|
|
struct First<FirstType, Rest...> {
|
|
using Type = FirstType;
|
|
};
|
|
|
|
template <typename... Ts>
|
|
using First_t = typename First<Ts...>::Type;
|
|
|
|
// Utility to count the occurences of type T in the parameter pack Ts.
|
|
template <typename T, typename... Ts>
|
|
struct OccurencesOf : std::integral_constant<size_t, 0> {};
|
|
template <typename T, typename U>
|
|
struct OccurencesOf<T, U> : std::integral_constant<size_t, std::is_same<T, U>::value> {};
|
|
template <typename T, typename First, typename... Rest>
|
|
struct OccurencesOf<T, First, Rest...>
|
|
: std::integral_constant<size_t,
|
|
OccurencesOf<T, First>::value + OccurencesOf<T, Rest...>::value> {};
|
|
|
|
template <typename T, typename... Ts>
|
|
constexpr size_t occurencesOf = OccurencesOf<T, Ts...>::value;
|
|
|
|
// Utility to remove const, volatile, and reference qualifiers.
|
|
template <typename T>
|
|
using RemoveCvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
|
|
|
// Evaluates to truth-like when type T matches type U with cv-reference removed.
|
|
template <typename T, typename U>
|
|
using NotSameType = std::negation<std::is_same<T, RemoveCvref_t<U>>>;
|
|
|
|
// Concept helper for constructors.
|
|
template <typename... Conditions>
|
|
using RequiresConditions = std::enable_if_t<std::conjunction_v<Conditions...>, bool>;
|
|
|
|
// Concept helper for assignment operators.
|
|
template <typename Return, typename... Conditions>
|
|
using AssignmentRequiresConditions =
|
|
std::enable_if_t<std::conjunction_v<Conditions...>, std::add_lvalue_reference_t<Return>>;
|
|
|
|
// Evaluates to true when every element type of Ts is trivially destructible.
|
|
template <typename... Ts>
|
|
constexpr bool isTriviallyDestructible = std::conjunction_v<std::is_trivially_destructible<Ts>...>;
|
|
|
|
// Evaluates to true when every element type of Ts is trivially copyable.
|
|
template <typename... Ts>
|
|
constexpr bool isTriviallyCopyable =
|
|
(std::conjunction_v<std::is_trivially_copy_assignable<Ts>...> &&
|
|
std::conjunction_v<std::is_trivially_copy_constructible<Ts>...>);
|
|
|
|
// Evaluates to true when every element type of Ts is trivially movable.
|
|
template <typename... Ts>
|
|
constexpr bool isTriviallyMovable =
|
|
(std::conjunction_v<std::is_trivially_move_assignable<Ts>...> &&
|
|
std::conjunction_v<std::is_trivially_move_constructible<Ts>...>);
|
|
|
|
// Enable if relational operator is convertible to bool and the optional
|
|
// conditions are true.
|
|
template <typename Op, typename... Conditions>
|
|
using enable_relop_t =
|
|
std::enable_if_t<(std::is_convertible<Op, bool>::value && std::conjunction_v<Conditions...>),
|
|
bool>;
|
|
|
|
template <typename T>
|
|
struct Identity {
|
|
using Type = T;
|
|
};
|
|
|
|
// Evaluates to true when T is an unbounded array.
|
|
template <typename T>
|
|
struct IsUnboundedArray : std::conjunction<std::is_array<T>, std::negation<std::extent<T>>> {};
|
|
|
|
// Returns true when T is a complete type or an unbounded array.
|
|
template <typename T, size_t = sizeof(T)>
|
|
constexpr bool isCompleteOrUnboundedArray(Identity<T>) {
|
|
return true;
|
|
}
|
|
template <typename Identity, typename T = typename Identity::Type>
|
|
constexpr bool isCompleteOrUnboundedArray(Identity) {
|
|
return std::disjunction<std::is_reference<T>, std::is_function<T>, std::is_void<T>,
|
|
IsUnboundedArray<T>>::value;
|
|
}
|
|
|
|
// Using swap for ADL. This directive is contained within the fit::internal
|
|
// namespace, which prevents leaking std::swap into user namespaces. Doing this
|
|
// at namespace scope is necessary to lookup swap via ADL while preserving the
|
|
// noexcept() specification of the resulting lookup.
|
|
using std::swap;
|
|
|
|
// Evaluates to true when T is swappable.
|
|
template <typename T, typename = void>
|
|
struct IsSwappable : std::false_type {
|
|
static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
|
|
"T must be a complete type or an unbounded array!");
|
|
};
|
|
template <typename T>
|
|
struct IsSwappable<T, std::void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))>>
|
|
: std::true_type {
|
|
static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
|
|
"T must be a complete type or an unbounded array!");
|
|
};
|
|
|
|
// Evaluates to true when T is nothrow swappable.
|
|
template <typename T, typename = void>
|
|
struct IsNothrowSwappable : std::false_type {
|
|
static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
|
|
"T must be a complete type or an unbounded array!");
|
|
};
|
|
template <typename T>
|
|
struct IsNothrowSwappable<T, std::void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))>>
|
|
: std::integral_constant<bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))> {
|
|
static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
|
|
"T must be a complete type or an unbounded array!");
|
|
};
|
|
|
|
} // namespace internal
|
|
} // namespace fit
|
|
} // namespace android::base
|