/* * Copyright 2022 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. */ #include #include #include #include #include #include namespace android::test { namespace { // Keep in sync with example usage in header file. struct Id : ftl::Constructible, ftl::Equatable { using Constructible::Constructible; }; static_assert(!std::is_default_constructible_v); struct Color : ftl::DefaultConstructible, ftl::Equatable, ftl::Orderable { using DefaultConstructible::DefaultConstructible; }; static_assert(Color() == Color(0u)); static_assert(ftl::to_underlying(Color(-1)) == 255u); static_assert(Color(1u) < Color(2u)); struct Sequence : ftl::DefaultConstructible, ftl::Equatable, ftl::Orderable, ftl::Incrementable { using DefaultConstructible::DefaultConstructible; }; static_assert(Sequence() == Sequence(-1)); struct Timeout : ftl::DefaultConstructible, ftl::Equatable, ftl::Addable { using DefaultConstructible::DefaultConstructible; }; using namespace std::chrono_literals; static_assert(Timeout() + Timeout(5s) == Timeout(15s)); // Construction. constexpr Id kId{1234}; constexpr Sequence kSequence; // Underlying value. static_assert(ftl::to_underlying(Id(-42)) == -42); static_assert(ftl::to_underlying(kSequence) == -1); // Casting. static_assert(static_cast(Id(-1)) == -1); static_assert(static_cast(kSequence) == -1); static_assert(!std::is_convertible_v); static_assert(!std::is_convertible_v); // Equality. static_assert(kId == Id(1234)); static_assert(kId != Id(123)); static_assert(kSequence == Sequence(-1)); // Ordering. static_assert(Sequence(1) < Sequence(2)); static_assert(Sequence(2) > Sequence(1)); static_assert(Sequence(3) <= Sequence(4)); static_assert(Sequence(4) >= Sequence(3)); static_assert(Sequence(5) <= Sequence(5)); static_assert(Sequence(6) >= Sequence(6)); // Incrementing. template constexpr auto mutable_op(Op op, T lhs, Ts... rhs) { const T result = op(lhs, rhs...); return std::make_pair(lhs, result); } static_assert(mutable_op([](auto& lhs) { return ++lhs; }, Sequence()) == std::make_pair(Sequence(0), Sequence(0))); static_assert(mutable_op([](auto& lhs) { return lhs++; }, Sequence()) == std::make_pair(Sequence(0), Sequence(-1))); // Addition. // `Addable` implies `Incrementable`. static_assert(mutable_op([](auto& lhs) { return ++lhs; }, Timeout()) == std::make_pair(Timeout(11s), Timeout(11s))); static_assert(mutable_op([](auto& lhs) { return lhs++; }, Timeout()) == std::make_pair(Timeout(11s), Timeout(10s))); static_assert(Timeout(5s) + Timeout(6s) == Timeout(11s)); static_assert(mutable_op([](auto& lhs, const auto& rhs) { return lhs += rhs; }, Timeout(7s), Timeout(8s)) == std::make_pair(Timeout(15s), Timeout(15s))); // Type safety. namespace traits { template struct is_incrementable : std::false_type {}; template struct is_incrementable())>> : std::true_type {}; template constexpr bool is_incrementable_v = is_incrementable{}; template struct has_binary_op : std::false_type {}; template struct has_binary_op(), std::declval()))>> : std::true_type {}; template constexpr bool is_equatable_v = has_binary_op, T, U>{} && has_binary_op, T, U>{}; template constexpr bool is_orderable_v = has_binary_op, T, U>{} && has_binary_op, T, U>{} && has_binary_op, T, U>{} && has_binary_op, T, U>{}; template constexpr bool is_addable_v = has_binary_op, T, U>{}; } // namespace traits struct Real : ftl::Constructible { using Constructible::Constructible; }; static_assert(traits::is_equatable_v); static_assert(!traits::is_equatable_v); static_assert(!traits::is_equatable_v); static_assert(!traits::is_equatable_v); static_assert(!traits::is_equatable_v); static_assert(!traits::is_equatable_v); static_assert(traits::is_orderable_v); static_assert(!traits::is_orderable_v); static_assert(!traits::is_orderable_v); static_assert(!traits::is_orderable_v); static_assert(!traits::is_orderable_v); static_assert(!traits::is_orderable_v); static_assert(traits::is_incrementable_v); static_assert(traits::is_incrementable_v); static_assert(!traits::is_incrementable_v); static_assert(!traits::is_incrementable_v); static_assert(!traits::is_incrementable_v); static_assert(traits::is_addable_v); static_assert(!traits::is_addable_v); static_assert(!traits::is_addable_v); static_assert(!traits::is_addable_v); static_assert(!traits::is_addable_v); static_assert(!traits::is_addable_v); } // namespace } // namespace android::test