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