TConcepts.cpp
Go to the documentation of this file.
#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&>));
}
}
test_concepts::Derived1
Definition: TConcepts.cpp:54
utl::Swappable
_utlConcept Swappable
Definition: stl.h:425
test_concepts::HavePerfectForwarding
Definition: TConcepts.cpp:50
test_concepts::Base
Definition: TConcepts.cpp:53
test_concepts::operator<=
bool operator<=(const B &l, const B &r)
Definition: TConcepts.cpp:84
meta.h
Include all meta library.
test_concepts
Definition: TConcepts.cpp:25
test_concepts::Incr::operator++
Incr & operator++()
Definition: TConcepts.cpp:406
test_concepts::HaveOnlyCopy
Definition: TConcepts.cpp:32
test_concepts::HaveCopyAndMove
Definition: TConcepts.cpp:44
utl::Assignable
_utlConcept Assignable
Definition: stl.h:366
utl::ConvertibleTo
_utlConcept ConvertibleTo
Definition: stl.h:87
test_concepts::Pred
Definition: TConcepts.cpp:381
gtest.h
utl::Same
_utlConcept Same
Definition: stl.h:62
test_concepts::type_printer
int type_printer(int *i)
Definition: TConcepts.cpp:409
test_concepts::operator!=
bool operator!=(const A &l, const A &r)
Definition: TConcepts.cpp:70
test_concepts::A::a_
int a_
Definition: TConcepts.cpp:63
utl::meta::int_
integral_< int, v > int_
int_ type: integral constant wrapper for int
Definition: integral.h:98
utl::CommonReference
_utlConcept CommonReference
Definition: stl.h:293
test_concepts::B::b_
int b_
Definition: TConcepts.cpp:73
test_concepts::Empty
Definition: TConcepts.cpp:31
concepts.h
Concepts main include header.
utl::DerivedFrom
_utlConcept DerivedFrom
Definition: stl.h:71
utl::meta::uint16_
integral_< uint16_t, v > uint16_
uint16_ type: integral constant wrapper for uint16_t
Definition: integral.h:83
utl
STL&#39;s core language concepts.
Definition: _1wire.h:30
test_concepts::A::A
A(int a=0)
Definition: TConcepts.cpp:65
test_concepts::Inv
Definition: TConcepts.cpp:377
test_concepts::operator<
bool operator<(const B &l, const B &r)
Definition: TConcepts.cpp:83
test_concepts::B::B
B(int b=0)
Definition: TConcepts.cpp:75
test_concepts::Incr::operator++
Incr operator++(int)
Definition: TConcepts.cpp:407
utl::Integral
_utlConcept Integral
Definition: stl.h:340
test_concepts::HaveOnlyMove
Definition: TConcepts.cpp:38
test_concepts::operator>
bool operator>(const B &l, const B &r)
Definition: TConcepts.cpp:85
utl::UnsignedIntegral
_utlConcept UnsignedIntegral
Definition: stl.h:352
test_concepts::HaveOperatorBase::base
Base base
Definition: TConcepts.cpp:58
utl::Boolean
_utlConcept Boolean
Definition: stl.h:551
test_concepts::B
Definition: TConcepts.cpp:72
EXPECT_EQ
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:16643
test_concepts::operator>=
bool operator>=(const B &l, const B &r)
Definition: TConcepts.cpp:86
utl::Constructible
_utlConcept Constructible
Definition: stl.h:438
test_concepts::Derived2
Definition: TConcepts.cpp:55
test_concepts::Incr
Definition: TConcepts.cpp:405
test_concepts::HavePerfectForwarding::HavePerfectForwarding
HavePerfectForwarding(T &&)
Definition: TConcepts.cpp:51
utl::meta::int16_
integral_< int16_t, v > int16_
int16_ type: integral constant wrapper for int16_t
Definition: integral.h:80
test_concepts::TEST
TEST(TConcepts, Same)
Definition: TConcepts.cpp:89
test_concepts::HaveOperatorBase
Definition: TConcepts.cpp:56
test_concepts::A
Definition: TConcepts.cpp:62
utl::SignedIntegral
_utlConcept SignedIntegral
Definition: stl.h:346
test_concepts::operator==
bool operator==(const A &l, const A &r)
Definition: TConcepts.cpp:69