|
- /*!
- * \file Tmeta.cpp
- *
- * Copyright (C) 2018 Christos Choutouridis
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #include <utl/concepts/concepts.h>
- #include <utl/meta/meta.h>
- #include <gtest/gtest.h>
-
-
- namespace test_concepts {
- using namespace utl;
-
- /*
- * Fixture like types
- */
- struct Empty { };
- struct HaveOnlyCopy {
- HaveOnlyCopy(const HaveOnlyCopy&) = default;
- HaveOnlyCopy(HaveOnlyCopy&&) = delete;
- HaveOnlyCopy& operator= (const HaveOnlyCopy&) = default;
- HaveOnlyCopy& operator= (HaveOnlyCopy&&) = delete;
- };
- struct HaveOnlyMove {
- HaveOnlyMove(const HaveOnlyMove&) = delete;
- HaveOnlyMove(HaveOnlyMove&&) = default;
- HaveOnlyMove& operator= (const HaveOnlyMove&) = delete;
- HaveOnlyMove& operator= (HaveOnlyMove&&) = default;
- };
- struct HaveCopyAndMove {
- HaveCopyAndMove(const HaveCopyAndMove&) = default;
- HaveCopyAndMove(HaveCopyAndMove&&) = default;
- HaveCopyAndMove& operator= (const HaveCopyAndMove&) = default;
- HaveCopyAndMove& operator= (HaveCopyAndMove&&) = default;
- };
- class HavePerfectForwarding {
- public: template<class T> HavePerfectForwarding(T&&) { }
- };
- class Base { };
- class Derived1 : public Base { };
- class Derived2 : public Derived1 { };
- class HaveOperatorBase {
- public: operator Base() { return base; }
- Base base;
- };
-
-
- struct A {
- int a_;
- public:
- A(int a =0) : a_{a} { };
- A(const A&) = default;
- A(A&&) = default;
- };
- bool operator== (const A& l, const A& r) { return l.a_ == r.a_; }
- bool operator!= (const A& l, const A& r) { return l.a_ != r.a_; }
-
- struct B {
- int b_;
- public:
- B(int b =0) : b_{b} { };
- B(const B&) = default;
- B(B&&) = default;
- B& operator= (const B&) = default;
- B& operator= (B&&) = default;
- };
- bool operator== (const B& l, const B& r) { return l.b_ == r.b_; }
- bool operator!= (const B& l, const B& r) { return l.b_ != r.b_; }
- bool operator< (const B& l, const B& r) { return l.b_ < r.b_; }
- bool operator<= (const B& l, const B& r) { return l.b_ <= r.b_; }
- bool operator> (const B& l, const B& r) { return l.b_ > r.b_; }
- bool operator>= (const B& l, const B& r) { return l.b_ >= r.b_; }
-
-
- TEST(TConcepts, Same) {
- // Same
- EXPECT_EQ (true, (Same<int, int>));
- EXPECT_EQ (false, (Same<int, long>));
- EXPECT_EQ (true, (Same<int*, int*>));
- EXPECT_EQ (true, (Same<double&, double&>));
- EXPECT_EQ (false, (Same<int, Empty>));
- EXPECT_EQ (false, (Same<Base, Derived1>));
- }
-
- TEST(TConcepts, DerivedFrom) {
- // DerivedFrom
- EXPECT_EQ (true, (DerivedFrom<Derived1, Base>));
- EXPECT_EQ (true, (DerivedFrom<Derived2, Derived1>));
- EXPECT_EQ (true, (DerivedFrom<Derived2, Base>));
- EXPECT_EQ (false, (DerivedFrom<Base, Derived1>));
- EXPECT_EQ (false, (DerivedFrom<Base, int>));
- EXPECT_EQ (false, (DerivedFrom<void, int>));
- }
-
- TEST(TConcepts, ConvertibleTo) {
- // ConvertibleTo
- EXPECT_EQ (true, (ConvertibleTo<void, void>));
- EXPECT_EQ (false, (ConvertibleTo<Base, void>));
- EXPECT_EQ (false, (ConvertibleTo<Base*, Derived1*>));
- EXPECT_EQ (true, (ConvertibleTo<Derived1*, Base*>));
- EXPECT_EQ (true, (ConvertibleTo<HaveOperatorBase, Base>));
- EXPECT_EQ (true, (ConvertibleTo<Base, HavePerfectForwarding>));
- }
-
- TEST(TConcepts, CommonReference) {
- // CommonReference
- EXPECT_EQ (true, (CommonReference<Derived1, Base>));
- EXPECT_EQ (true, (CommonReference<Derived1&, Base>));
- EXPECT_EQ (true, (CommonReference<const Empty&&, const Empty&>));
- EXPECT_EQ (false, (CommonReference<Empty&, const volatile Empty&>));
- //FIXME: CommonReference needs SFINAE friendly implementation
- //EXPECT_EQ (false, (CommonReference<Empty&&, const volatile Empty&>)); <- yields compiler error
-
- // Common
- EXPECT_EQ (true, (Common<int, int>));
- EXPECT_EQ (true, (Common<Base, Derived1>));
- EXPECT_EQ (true, (Common<Derived1, Derived2>));
- EXPECT_EQ (true, (Common<Base, HaveOperatorBase>));
- EXPECT_EQ (true, (Common<Base, HavePerfectForwarding>));
- }
-
- TEST(TConcepts, Integral) {
- // Integral
- EXPECT_EQ (false, (Integral<void>));
- EXPECT_EQ (true, (Integral<int>));
- EXPECT_EQ (true, (Integral<bool>));
- EXPECT_EQ (false, (Integral<int*>));
- EXPECT_EQ (false, (Integral<Base>));
- EXPECT_EQ (true, (Integral<meta::int_<42>::value_type>));
- EXPECT_EQ (false, (Integral<meta::int_<42>::type>));
-
- // SignedIntegral
- EXPECT_EQ (false, (SignedIntegral<void>));
- EXPECT_EQ (true, (SignedIntegral<int>));
- EXPECT_EQ (false, (SignedIntegral<int*>));
- EXPECT_EQ (false, (SignedIntegral<unsigned long>));
- EXPECT_EQ (false, (SignedIntegral<double>));
- EXPECT_EQ (false, (SignedIntegral<Base>));
- EXPECT_EQ (true, (SignedIntegral<meta::int16_<42>::value_type>));
-
- // UnsignedIntegral
- EXPECT_EQ (false, (UnsignedIntegral<void>));
- EXPECT_EQ (true, (UnsignedIntegral<unsigned int>));
- EXPECT_EQ (false, (UnsignedIntegral<long>));
- EXPECT_EQ (false, (UnsignedIntegral<double>));
- EXPECT_EQ (false, (UnsignedIntegral<Base>));
- EXPECT_EQ (true, (UnsignedIntegral<meta::uint16_<42>::value_type>));
- }
-
- TEST(TConcepts, Assignable) {
- // MoveAssignable
- EXPECT_EQ (false, (MoveAssignable<void>));
- EXPECT_EQ (true, (MoveAssignable<void*>));
- EXPECT_EQ (true, (MoveAssignable<int>));
- EXPECT_EQ (true, (MoveAssignable<int*>));
- EXPECT_EQ (false, (MoveAssignable<HaveOnlyCopy>));
- EXPECT_EQ (true, (MoveAssignable<HaveOnlyMove>));
- EXPECT_EQ (true, (MoveAssignable<HaveCopyAndMove>));
- EXPECT_EQ (true, (MoveAssignable<Empty>));
- EXPECT_EQ (true, (MoveAssignable<HavePerfectForwarding>));
-
- // CopyAssignable
- EXPECT_EQ (false, (CopyAssignable<void>));
- EXPECT_EQ (true, (CopyAssignable<void*>));
- EXPECT_EQ (true, (CopyAssignable<int>));
- EXPECT_EQ (true, (CopyAssignable<int*>));
- EXPECT_EQ (true, (CopyAssignable<HaveOnlyCopy>));
- EXPECT_EQ (false, (CopyAssignable<HaveOnlyMove>));
- EXPECT_EQ (true, (CopyAssignable<HaveCopyAndMove>));
- EXPECT_EQ (true, (CopyAssignable<Empty>));
- EXPECT_EQ (true, (CopyAssignable<HavePerfectForwarding>));
-
- // Assignable
- EXPECT_EQ (false, (Assignable<void, void>));
- EXPECT_EQ (false, (Assignable<int&, void>));
- EXPECT_EQ (true, (Assignable<int&, int>));
- EXPECT_EQ (false, (Assignable<int, int>));
- EXPECT_EQ (false, (Assignable<int*, int*>));
- EXPECT_EQ (true, (Assignable<Base&, Derived1>));
- EXPECT_EQ (false, (Assignable<Derived1&, Base>));
- EXPECT_EQ (true, (Assignable<HaveOnlyMove&, HaveOnlyMove&&>));
- EXPECT_EQ (true , (Assignable<HaveOnlyMove&, HaveOnlyMove>));
- EXPECT_EQ (true, (Assignable<Empty&, Empty>));
- }
-
- TEST(TConcepts, Swappable) {
- // Swappable, SwappableWith
- EXPECT_EQ (false, (Swappable<void>));
- EXPECT_EQ (true, (Swappable<void*>));
- EXPECT_EQ (true, (Swappable<int>));
- EXPECT_EQ (true, (Swappable<Base>));
- EXPECT_EQ (true, (SwappableWith<int, int>));
- EXPECT_EQ (false, (SwappableWith<int, Base>));
- EXPECT_EQ (false, (SwappableWith<Base, Derived1>));
-
- // Destructible
- EXPECT_EQ (false, (Destructible<void>));
- EXPECT_EQ (true, (Destructible<void*>));
- EXPECT_EQ (true, (Destructible<int>));
- EXPECT_EQ (true, (Destructible<int&>));
- EXPECT_EQ (true, (Destructible<Base>));
- EXPECT_EQ (true, (Destructible<HavePerfectForwarding>));
- }
-
- TEST(TConcepts, Constructible) {
- // Constructible
- EXPECT_EQ (false, (Constructible<void>));
- EXPECT_EQ (true, (Constructible<void*>));
- EXPECT_EQ (true, (Constructible<Base>));
- EXPECT_EQ (false, (Constructible<HaveOnlyMove>));
- EXPECT_EQ (true, (Constructible<HavePerfectForwarding, int>));
-
- // DefaultConstructible
- EXPECT_EQ (false, (DefaultConstructible<void>));
- EXPECT_EQ (true, (DefaultConstructible<void*>));
- EXPECT_EQ (false, (DefaultConstructible<int&>));
- EXPECT_EQ (true, (DefaultConstructible<Base>));
- EXPECT_EQ (true, (DefaultConstructible<Derived1>));
- EXPECT_EQ (false, (DefaultConstructible<HaveOnlyCopy>));
- EXPECT_EQ (false, (DefaultConstructible<HaveOnlyMove>));
- EXPECT_EQ (false, (DefaultConstructible<HavePerfectForwarding>));
-
- // MoveConstructible
- EXPECT_EQ (false, (MoveConstructible<void>));
- EXPECT_EQ (true, (MoveConstructible<void*>));
- EXPECT_EQ (true, (MoveConstructible<Base>));
- EXPECT_EQ (true, (MoveConstructible<Derived1>));
- EXPECT_EQ (true, (MoveConstructible<HaveOnlyMove>));
- EXPECT_EQ (false, (MoveConstructible<HaveOnlyCopy>));
- EXPECT_EQ (true, (MoveConstructible<HaveCopyAndMove>));
- EXPECT_EQ (true , (MoveConstructible<HavePerfectForwarding>));
-
- // CopyConstructible
- EXPECT_EQ (false, (CopyConstructible<void>));
- EXPECT_EQ (true, (CopyConstructible<void*>));
- EXPECT_EQ (true, (CopyConstructible<Base>));
- EXPECT_EQ (true, (CopyConstructible<Derived1>));
- EXPECT_EQ (false, (CopyConstructible<HaveOnlyMove>));
- EXPECT_EQ (false, (CopyConstructible<HaveOnlyCopy>));
- EXPECT_EQ (true, (CopyConstructible<HaveCopyAndMove>));
- EXPECT_EQ (true , (CopyConstructible<HavePerfectForwarding>));
- }
-
- TEST(TConcepts, MovableCopyable) {
- // Movable
- EXPECT_EQ (false, (Movable<void>));
- EXPECT_EQ (true, (Movable<int>));
- EXPECT_EQ (true, (Movable<Base>));
- EXPECT_EQ (true, (Movable<Derived1>));
- EXPECT_EQ (true, (Movable<HaveOnlyMove>));
- EXPECT_EQ (false, (Movable<HaveOnlyCopy>));
- EXPECT_EQ (true, (Movable<HaveCopyAndMove>));
- EXPECT_EQ (true , (Movable<HavePerfectForwarding>));
-
- // Copyable
- EXPECT_EQ (false, (Copyable<void>));
- EXPECT_EQ (true, (Copyable<int>));
- EXPECT_EQ (true, (Copyable<Base>));
- EXPECT_EQ (true, (Copyable<Derived1>));
- EXPECT_EQ (false, (Copyable<HaveOnlyMove>));
- EXPECT_EQ (false, (Copyable<HaveOnlyCopy>));
- EXPECT_EQ (true, (Copyable<HaveCopyAndMove>));
- EXPECT_EQ (true , (Copyable<HavePerfectForwarding>));
- }
-
- TEST(TConcepts, Boolean) {
- // Boolean
- EXPECT_EQ (false, (Boolean<void>));
- EXPECT_EQ (true, (Boolean<bool>));
- EXPECT_EQ (true, (Boolean<int>));
- EXPECT_EQ (true, (Boolean<double>));
- EXPECT_EQ (true, (Boolean<std::true_type>));
- EXPECT_EQ (true, (Boolean<meta::true_>));
- EXPECT_EQ (false, (Boolean<Empty>));
- }
-
- TEST(TConcepts, Comparable) {
- // EqualityComparable
- EXPECT_EQ (false, (EqualityComparable<void>));
- EXPECT_EQ (true, (EqualityComparable<bool>));
- EXPECT_EQ (true, (EqualityComparable<int>));
- EXPECT_EQ (false, (EqualityComparable<Empty>));
- EXPECT_EQ (true, (EqualityComparable<A>));
-
- // EqualityComparableWith
- EXPECT_EQ (false, (EqualityComparableWith<void, bool>));
- EXPECT_EQ (false, (EqualityComparableWith<void, void>));
- EXPECT_EQ (true, (EqualityComparableWith<bool, bool>));
- EXPECT_EQ (true, (EqualityComparableWith<int, int>));
- EXPECT_EQ (true, (EqualityComparableWith<int, bool>));
- EXPECT_EQ (false, (EqualityComparableWith<Empty, Empty>));
- EXPECT_EQ (false, (EqualityComparableWith<int, Empty>));
- EXPECT_EQ (true, (EqualityComparableWith<A, A>));
- EXPECT_EQ (false, (EqualityComparableWith<A, B>));
-
- // StrictTotallyOrdered
- EXPECT_EQ (false, (StrictTotallyOrdered<void>));
- EXPECT_EQ (true, (StrictTotallyOrdered<bool>));
- EXPECT_EQ (true, (StrictTotallyOrdered<int>));
- EXPECT_EQ (true, (StrictTotallyOrdered<double>));
- EXPECT_EQ (false, (StrictTotallyOrdered<Empty>));
- EXPECT_EQ (false, (StrictTotallyOrdered<A>));
- EXPECT_EQ (true, (StrictTotallyOrdered<B>));
-
- // StrictTotallyOrderedWith
- EXPECT_EQ (false, (StrictTotallyOrderedWith<void, void>));
- EXPECT_EQ (false, (StrictTotallyOrderedWith<int, void>));
- EXPECT_EQ (true, (StrictTotallyOrderedWith<bool, bool>));
- EXPECT_EQ (true, (StrictTotallyOrderedWith<int, double>));
- EXPECT_EQ (false, (StrictTotallyOrderedWith<int, Empty>));
- EXPECT_EQ (false, (StrictTotallyOrderedWith<Base, Derived1>));
- EXPECT_EQ (false, (StrictTotallyOrderedWith<A, A>));
- EXPECT_EQ (true, (StrictTotallyOrderedWith<B, B>));
- EXPECT_EQ (false, (StrictTotallyOrderedWith<A, B>));
- }
-
- TEST(TConcepts, Types) {
- // Semiregular
- EXPECT_EQ (false, (Semiregular<void>));
- EXPECT_EQ (true, (Semiregular<int>));
- EXPECT_EQ (true, (Semiregular<Empty>));
- EXPECT_EQ (false, (Semiregular<HaveOnlyMove>));
- EXPECT_EQ (false, (Semiregular<HaveOnlyCopy>));
- EXPECT_EQ (false, (Semiregular<HaveCopyAndMove>));
- EXPECT_EQ (false, (Semiregular<A>));
- EXPECT_EQ (true, (Semiregular<B>));
-
- // Regular
- EXPECT_EQ (false, (Regular<void>));
- EXPECT_EQ (true, (Regular<int>));
- EXPECT_EQ (true, (Regular<int*>));
- EXPECT_EQ (false, (Regular<Empty>));
- EXPECT_EQ (false, (Regular<HaveOnlyMove>));
- EXPECT_EQ (false, (Regular<HaveOnlyCopy>));
- EXPECT_EQ (false, (Regular<HaveCopyAndMove>));
- EXPECT_EQ (false, (Regular<A>));
- EXPECT_EQ (true, (Regular<B>));
-
- // Scalar
- EXPECT_EQ (false, (Scalar<void>));
- EXPECT_EQ (true, (Scalar<int>));
- EXPECT_EQ (true, (Scalar<long*>));
- EXPECT_EQ (false, (Scalar<A>));
- EXPECT_EQ (false, (Scalar<B>));
-
- // Arithmetic
- EXPECT_EQ (false, (Arithmetic<void>));
- EXPECT_EQ (true, (Arithmetic<int>));
- EXPECT_EQ (false, (Arithmetic<long*>));
- EXPECT_EQ (false, (Arithmetic<A>));
- EXPECT_EQ (false, (Arithmetic<B>));
-
- // FloatingPoint
- EXPECT_EQ (false, (FloatingPoint<void>));
- EXPECT_EQ (true, (FloatingPoint<float>));
- EXPECT_EQ (true, (FloatingPoint<double>));
- EXPECT_EQ (false, (FloatingPoint<int>));
- EXPECT_EQ (false, (FloatingPoint<float*>));
- EXPECT_EQ (false, (FloatingPoint<A>));
- EXPECT_EQ (false, (FloatingPoint<B>));
- }
-
- struct Inv {
- void operator() (int) { };
- void operator() () { };
- };
- struct Pred {
- bool operator () (int) { return true; }
- bool operator () (int, int) { return true; }
- };
- TEST(TConcepts, Callable) {
- EXPECT_EQ (true, (Invocable<Inv, int>));
- EXPECT_EQ (true, (Invocable<Inv>));
- EXPECT_EQ (true, (Invocable<Inv, double>));
- EXPECT_EQ (false, (Invocable<Inv, Empty>));
-
- EXPECT_EQ (true, (RegularInvocable<Inv, int>));
-
- EXPECT_EQ (false, (Predicate<Inv, int>));
- EXPECT_EQ (true, (Predicate<Pred, int>));
- EXPECT_EQ (false, (Predicate<Pred, Empty>));
-
- EXPECT_EQ (true, (Relation<Pred, int, int>));
- EXPECT_EQ (true, (Relation<Pred, int, double>));
- EXPECT_EQ (false, (Relation<Pred, Empty, int>));
-
- EXPECT_EQ (true, (StrictWeakOrder<Pred, int, int>));
- EXPECT_EQ (false, (StrictWeakOrder<Pred, int, Empty>));
- }
-
- struct Incr {
- Incr& operator++() { return *this; }
- Incr operator++(int) { return *this; }
- };
- int type_printer (int* i) { return *i; }
- TEST(TConcepts, Iterators) {
-
- // type_printer(detail::try_ppI<Incr&>{});
- // type_printer(detail::try_Ipp<Incr&>{});
- // type_printer(meta::detected_t<detail::try_ppI, int>{});
- EXPECT_EQ (true, (WeaklyIncrementable<int>));
- EXPECT_EQ (false, (WeaklyIncrementable<void>));
- EXPECT_EQ (false, (WeaklyIncrementable<meta::nil_>));
- EXPECT_EQ (true, (WeaklyIncrementable<Incr>));
- EXPECT_EQ (false, (WeaklyIncrementable<Incr&>));
- }
- }
-
|