1 /*=============================================================================
2 Copyright (c) 2017 Paul Fultz II
3 test.hpp
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 #ifndef GUARD_TEST_H
8 #define GUARD_TEST_H
9
10 #include <type_traits>
11 #include <tuple>
12 #include <iostream>
13 #include <functional>
14 #include <vector>
15 #include <memory>
16 #include <boost/hof/detail/forward.hpp>
17
18 #ifndef BOOST_HOF_HAS_STATIC_TEST_CHECK
19 #if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) || defined(_MSC_VER)
20 #define BOOST_HOF_HAS_STATIC_TEST_CHECK 0
21 #else
22 #define BOOST_HOF_HAS_STATIC_TEST_CHECK 1
23 #endif
24 #endif
25
26
27 #define BOOST_HOF_PP_CAT(x, y) BOOST_HOF_PP_PRIMITIVE_CAT(x, y)
28 #define BOOST_HOF_PP_PRIMITIVE_CAT(x, y) x ## y
29
30 namespace boost { namespace hof { namespace test {
31
32 typedef std::function<void()> test_case;
33 static std::vector<test_case> test_cases;
34
35 struct auto_register
36 {
auto_registerboost::hof::test::auto_register37 auto_register(test_case tc)
38 {
39 test_cases.push_back(tc);
40 }
41 };
42
43 #define BOOST_HOF_DETAIL_TEST_CASE(name) \
44 struct name \
45 { void operator()() const; }; \
46 static boost::hof::test::auto_register BOOST_HOF_PP_CAT(name, _register) = boost::hof::test::auto_register(name()); \
47 void name::operator()() const
48
49 template<class T>
50 T bare(const T&);
51
52 template<class T>
unused(T &&)53 inline void unused(T&&) {}
54
55 }}} // namespace boost::hof
56
57 #if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
58 #define BOOST_HOF_STATIC_AUTO constexpr auto
59 #else
60 #define BOOST_HOF_STATIC_AUTO const constexpr auto
61 #endif
62
63 #define STATIC_ASSERT_SAME(...) static_assert(std::is_same<__VA_ARGS__>::value, "Types are not the same")
64 #if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
65 #define STATIC_ASSERT_MOVE_ONLY(T)
66 #else
67 #define STATIC_ASSERT_MOVE_ONLY(T) static_assert(!std::is_copy_constructible<T>::value && std::is_move_constructible<T>::value, "Not movable")
68 #endif
69 #if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
70 #define STATIC_ASSERT_NOT_DEFAULT_CONSTRUCTIBLE(T)
71 #else
72 #define STATIC_ASSERT_NOT_DEFAULT_CONSTRUCTIBLE(T) static_assert(!std::is_default_constructible<T>::value, "Default constructible")
73 #endif
74 #define STATIC_ASSERT_EMPTY(x) static_assert(std::is_empty<decltype(boost::hof::test::bare(x))>::value, "Not empty");
75
76
77 #define BOOST_HOF_TEST_CASE() BOOST_HOF_DETAIL_TEST_CASE(BOOST_HOF_PP_CAT(test_, __LINE__))
78 #define BOOST_HOF_STATIC_TEST_CASE() struct BOOST_HOF_PP_CAT(test_, __LINE__)
79
80 #define BOOST_HOF_TEST_TEMPLATE(...) typedef std::integral_constant<int, sizeof(__VA_ARGS__)> BOOST_HOF_PP_CAT(test_template_, __LINE__)
81
82 #define BOOST_HOF_TEST_CHECK(...) if (!(__VA_ARGS__)) std::cout << "***** FAILED *****: " << #__VA_ARGS__ << "@" << __FILE__ << ": " << __LINE__ << std::endl
83 #define BOOST_HOF_STRINGIZE(...) #__VA_ARGS__
84
85 #if BOOST_HOF_HAS_STATIC_TEST_CHECK
86 #define BOOST_HOF_STATIC_TEST_CHECK(...) static_assert(__VA_ARGS__, BOOST_HOF_STRINGIZE(__VA_ARGS__))
87 #else
88 #define BOOST_HOF_STATIC_TEST_CHECK(...)
89 #endif
90
91 #ifndef BOOST_HOF_HAS_CONSTEXPR_TUPLE
92 #define BOOST_HOF_HAS_CONSTEXPR_TUPLE BOOST_HOF_HAS_STD_14
93 #endif
94
95 struct binary_class
96 {
97 template<class T, class U>
operator ()binary_class98 constexpr T operator()(T x, U y) const noexcept
99 {
100 return x+y;
101 }
102
103 };
104
105 struct mutable_class
106 {
107 template<class F>
108 struct result;
109
110 template<class F, class T, class U>
111 struct result<F(T&, U)>
112 {
113 typedef T type;
114 };
115
116 template<class T, class U>
operator ()mutable_class117 T operator()(T & x, U y) const
118 {
119 return x+=y;
120 }
121
122 };
123
124 struct unary_class
125 {
126 template<class T>
operator ()unary_class127 constexpr T&& operator()(T&& x) const noexcept
128 {
129 return boost::hof::forward<T>(x);
130 }
131
132 };
133
134 struct void_class
135 {
136 template<class T>
operator ()void_class137 void operator()(T) const
138 {
139 }
140 };
141
142 struct mono_class
143 {
operator ()mono_class144 constexpr int operator()(int x) const
145 {
146 return x+1;
147 }
148 };
149
150 struct tuple_class
151 {
152 // Note: Taking the tuple by value causes the compiler to ICE on gcc 4.7
153 // when called in a constexpr context.
154 template<class T>
operator ()tuple_class155 constexpr int operator()(const T& t) const
156 {
157 return std::get<0>(t) + 1;
158 }
159 };
160
161 template<class R>
162 struct explicit_class
163 {
164 template<class T>
operator ()explicit_class165 R operator()(T x)
166 {
167 return static_cast<R>(x);
168 }
169 };
170
171 struct move_class
172 {
173 std::unique_ptr<int> i;
move_classmove_class174 move_class() : i(new int(0))
175 {}
176
177 template<class T, class U>
operator ()move_class178 constexpr T operator()(T x, U y) const
179 {
180 return x+y+*i;
181 }
182 };
183
main()184 int main()
185 {
186 for(const auto& tc: boost::hof::test::test_cases) tc();
187 return 0;
188 }
189
190 #endif
191