EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TypeTraitsTest.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TypeTraitsTest.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <boost/test/data/test_case.hpp>
10 #include <boost/test/unit_test.hpp>
11 
13 
14 namespace bdata = boost::unit_test::data;
15 namespace tt = boost::test_tools;
16 
17 using namespace Acts::Concepts;
18 
19 namespace Acts {
20 
21 namespace Test {
22 BOOST_AUTO_TEST_SUITE(Surfaces)
23 
24 // generate traits for methods named foo and bar
25 METHOD_TRAIT(foo_method_t, foo);
26 METHOD_TRAIT(bar_method_t, bar);
27 
28 struct E {
29  int bar(const double&) { return 5; }
30 };
31 
32 struct E2 {
33  int bar(const double&) const { return 5; }
34 };
35 
36 class E3 {
37  int bar(const double&) { return 5; }
38 };
39 
40 BOOST_AUTO_TEST_CASE(TypeTraitsMethods) {
41  // E does not have a method bar without arguments
42  static_assert(!has_method<E, int, bar_method_t>, "failed");
43  // E does have a method like int bar(const double&)
44  static_assert(has_method<E, int, bar_method_t, const double&>, "failed");
45  // E does not have method bar returning double instead of int
46  static_assert(!has_method<E, double, bar_method_t, const double&>, "failed");
47  // E does not have method taking non-ref const double argument
48  static_assert(!has_method<E, int, bar_method_t, const double>, "failed");
49  // E does not have method taking non-const double ref argument
50  static_assert(!has_method<E, int, bar_method_t, double&>, "failed");
51  // E does not have method taking plain double argument
52  static_assert(!has_method<E, int, bar_method_t, double>, "failed");
53  // E does not have method const method with correct signature otherwise
54  // This test ensures a non-const method does not qualify for a
55  // check for a method on the const type
56  static_assert(!has_method<const E, int, bar_method_t, const double&>,
57  "failed");
58  // E does not have a foo method
59  static_assert(!has_method<E, int, foo_method_t, const double&>, "failed");
60 
61  // E2 doesnt have method like int bar()
62  static_assert(!has_method<E2, int, bar_method_t>, "failed");
63  // E2 does not have non-const method with signature int bar(const double&)
64  // This means that a const method won't fulfill a non-const method
65  // requirement
66  static_assert(!has_method<E2, int, bar_method_t, const double&>, "failed");
67  // E2 has method of signature int bar(const double&) const
68  static_assert(has_method<const E2, int, bar_method_t, const double&>,
69  "failed");
70  // E2 does not have method taking non-ref const double
71  static_assert(!has_method<E2, int, bar_method_t, const double>, "failed");
72  // E2 does not have method taking non-const ref double
73  static_assert(!has_method<E2, int, bar_method_t, double&>, "failed");
74  // E2 does not have method taking plain double
75  static_assert(!has_method<E2, int, bar_method_t, double>, "failed");
76  // E2 does not have method with char return type
77  static_assert(!has_method<const E2, char, bar_method_t, const double&>,
78  "failed");
79  // E2 does not have foo method
80  static_assert(!has_method<const E2, int, foo_method_t, const double&>,
81  "failed");
82 
83  // E3 does have a method like int bar(const double&) but is private
84  static_assert(!has_method<E3, int, bar_method_t, const double&>, "failed");
85 }
86 
87 // trait for member named "member_a"
88 template <typename T>
89 using member_a_t = decltype(std::declval<T>().member_a);
90 // trait for member named "member_b"
91 template <typename T>
92 using member_b_t = decltype(std::declval<T>().member_b);
93 
94 struct M {
95  int member_a;
96  double member_b;
97 };
98 
99 struct M2 {
100  double member_a;
101 };
102 
103 struct M3 {
104  char member_a;
105 };
106 
107 struct M4 {
108  char member_b;
109 };
110 
111 class M5 {
112  char member_b;
113 };
114 
115 BOOST_AUTO_TEST_CASE(TypeTraitsMember) {
116  static_assert(has_member<M, member_a_t, int>, "!");
117  static_assert(has_member<M, member_b_t, double>, "!");
118  // incorrect type
119  static_assert(!has_member<M, member_b_t, int>, "!");
120  static_assert(!has_member<M, member_a_t, double>, "!");
121 
122  static_assert(has_member<M2, member_a_t, double>, "!");
123  static_assert(!has_member<M2, member_a_t, int>, "!");
124 
125  static_assert(exists<member_a_t, M>, "!");
126  static_assert(exists<member_a_t, M2>, "!");
127  static_assert(exists<member_a_t, M3>, "!");
128  static_assert(!exists<member_a_t, M4>, "!");
129 
130  // private member is not detected
131  static_assert(!has_member<M5, member_b_t, char>, "!");
132 
133  // private member is not detected.
134  static_assert(!exists<member_b_t, M5>, "!");
135 }
136 
137 template <typename T>
138 using nested_a_t = typename T::NestedA;
139 template <typename T>
140 using nested_b_t = typename T::NestedB;
141 
142 struct N {
143  struct NestedA;
144  class NestedB;
145 };
146 
147 struct N2 {
148  struct NestedA;
149 };
150 
151 struct N3 {
152  class NestedB;
153 };
154 
155 BOOST_AUTO_TEST_CASE(TypeTraitsNestedType) {
156  static_assert(exists<nested_a_t, N>, "!");
157  static_assert(exists<nested_b_t, N>, "!");
158 
159  static_assert(exists<nested_a_t, N2>, "!");
160  static_assert(!exists<nested_b_t, N2>, "!");
161 
162  static_assert(!exists<nested_a_t, N3>, "!");
163  static_assert(exists<nested_b_t, N3>, "!");
164 }
165 
166 // trait for member named "member"
167 template <typename T>
168 using member_t = decltype(std::declval<T>().member);
169 
170 // trait for nested type called "Nested"
171 template <typename T>
172 using nested_t = typename T::Nested;
173 
174 // trait for contained template "meta" with two template params
175 template <typename T>
176 using meta_t = typename T::template meta<void, void>;
177 
178 // combine it into a concept
179 template <typename T>
180 constexpr bool SomeConcept =
181  require<has_method<T, double, foo_method_t, double, int>,
182  has_method<const T, bool, bar_method_t, double&&>,
183  has_member<T, member_t, bool>, exists<nested_t, T>,
184  exists<meta_t, T>>;
185 
186 struct A {
187  bool member;
188 
189  struct Nested {};
190 
191  template <typename U, typename V>
192  struct meta {};
193 
194  double foo(double, int) { return 5; }
195 
196  bool bar(double&&) const { return true; }
197 };
198 
199 struct A2 {
200  bool member;
201 
202  struct Nested {};
203 
204  template <typename U>
205  struct meta {};
206 
207  double foo(double, int) { return 5; }
208 
209  bool bar(double&&) const { return true; }
210 };
211 
212 struct B {
213  bool different;
214 
215  int foo(double) { return 5; }
216 };
217 
218 struct C {
219  double foo(int) { return 5; }
220 };
221 
222 struct D {
223  double bar(double) { return 5; }
224 };
225 
226 BOOST_AUTO_TEST_CASE(TypeTraitsConcepts) {
227  static_assert(SomeConcept<A>, "A does not fulfill \"SomeConcept\"");
228  static_assert(!SomeConcept<A2>, "A2 does not fulfill \"SomeConcept\"");
229  static_assert(!SomeConcept<B>, "B does fulfill \"SomeConcept\"");
230  static_assert(!SomeConcept<C>, "C does fulfill \"SomeConcept\"");
231  static_assert(!SomeConcept<D>, "D does fulfill \"SomeConcept\"");
232 }
233 
234 BOOST_AUTO_TEST_SUITE_END()
235 } // namespace Test
236 } // namespace Acts