MIRA
RPCPatternCheck.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_BASE_INCLUDE_RPC_RPCPATTERNCHECK_H_
48 #define _MIRA_BASE_INCLUDE_RPC_RPCPATTERNCHECK_H_
49 
50 #include <type_traits>
51 #include <string>
52 
53 namespace mira {
54 namespace Private {
55 
56 // Helper to detect whether the operator() exists
57 template<typename T>
59 {
60  typedef char one;
61  typedef long two;
62 
63  template<typename C>
64  static char test(decltype(&C::operator()));
65  template<typename C>
66  static long test(...);
67 
68 public:
69  constexpr static bool value = sizeof(test<T>(0)) == sizeof(char);
70 };
71 
72 // checks if the underlying type of B can be constructed by A
73 template<typename A, typename B>
74 static constexpr bool isConstr()
75 {
77  A&&>::value;
78 }
79 
80 // type that holds a parameter pack
81 template<typename... ARGS>
83 {};
84 
85 // SFINAE way to detect functions and get their return values
86 // It is by no means complete but checks the most relevant cases
87 template<class F, typename Enable = void>
89 {
90 public:
91  static constexpr bool isFunction = false;
92 };
93 
94 template<class F>
95 class FunctionTraits<F, typename std::enable_if<Private::HasParenthesis<F>::value>::type>
96 {
98 
99 public:
100  using ReturnValue = typename InternalParser::ReturnValue;
101  using Arguments = typename InternalParser::Arguments;
102 
103 public:
104  static constexpr bool isFunction = true;
105 };
106 
107 template<class F>
109 {};
110 
111 template<class F>
112 struct FunctionTraits<F&&> : public FunctionTraits<F>
113 {};
114 
115 // Function Pointer
116 template<class R, class... Args>
117 struct FunctionTraits<R (*)(Args...)> : public FunctionTraits<R(Args...)>
118 {};
119 
120 template<typename R, typename... Args>
121 class FunctionTraits<R(Args...)>
122 {
123 public:
124  using Arguments = ArgumentTuple<Args...>;
125  using ReturnValue = R;
126 
127  static constexpr bool isFunction = true;
128 };
129 
130 // member function pointer
131 template<class C, class R, class... Args>
132 class FunctionTraits<R (C::*)(Args...)> : public FunctionTraits<R(Args...)>
133 {};
134 
135 // const member function pointer
136 template<class C, class R, class... Args>
137 class FunctionTraits<R (C::*)(Args...) const> : public FunctionTraits<R(Args...)>
138 {};
139 
140 // member object pointer
141 template<class C, class R>
142 class FunctionTraits<R(C::*)> : public FunctionTraits<R()>
143 {};
144 
146 
147 namespace rpc {
148 
149 // correctPattern()/isValid(): general compile time arguments check
150 
151 template<typename... Args, typename... Descriptions>
152 constexpr typename std::enable_if<((sizeof...(Args)) * 3 != sizeof...(Descriptions)) &&
153  ((sizeof...(Args)) * 2 != sizeof...(Descriptions)), bool>::type
155 {
156  return false;
157 }
158 
159 constexpr bool
161 {
162  return true;
163 }
164 
165 template<typename HeadArg, typename... TailArgs, typename Name, typename Description, typename Example,
166  typename... TailDocs>
167 constexpr typename std::enable_if<(sizeof...(TailArgs)) * 3 == sizeof...(TailDocs), bool>::type
170 {
171  return isConstr<Example, HeadArg>() && isConstr<Name, std::string>()
172  && isConstr<Description, std::string>()
174 }
175 
176 template<typename HeadArg, typename... TailArgs, typename Name, typename Description,
177  typename... TailDocs>
178 constexpr typename std::enable_if<(sizeof...(TailArgs)) * 2 == sizeof...(TailDocs), bool>::type
181 {
182  return isConstr<Name, std::string>() && isConstr<Description, std::string>()
184 }
185 
186 template<typename HeadArg, typename... TailArgs>
188 {
189  return true;
190 }
191 
192 template<typename F, typename Comment, typename... Description>
193 constexpr typename std::enable_if<!FunctionTraits<F>::isFunction, bool>::type isValid()
194 {
195  return false;
196 }
197 
198 template<typename F, typename Comment, typename... Description>
199 constexpr typename std::enable_if<FunctionTraits<F>::isFunction, bool>::type isValid()
200 {
201  return Private::isConstr<Comment, std::string>()
202  && correctPattern(typename FunctionTraits<F>::Arguments(), Private::ArgumentTuple<Description...>());
203 }
204 
206 
207 // assertName/Description/Example(), patternError(), invalidAssertion():
208 // generate specific compile time error message
209 
210 template<typename T>
212 {
213  static_assert(
214  isConstr<T, std::string>(),
215  "_____________THE PROVIDED TYPE OF A PARAMETER NAME CAN NOT "
216  "BE USED TO INITIALIZE A STRING IN CALL TO Reflector::method(). "
217  "PLEASE PROVIDE NAME AND DESCRIPTION FOR EACH RPC METHOD PARAMETER, "
218  "OR NAME, DESCRIPTION AND A CORRECTLY TYPED SAMPLE VALUE FOR EACH PARAMETER_____________");
219 }
220 
221 template<typename T>
223 {
224  static_assert(
225  isConstr<T, std::string>(),
226  "_____________THE PROVIDED TYPE OF A PARAMETER DESCRIPTION CAN NOT BE USED "
227  "TO INITIALIZE A STRING IN CALL TO Reflector::method(). "
228  "PLEASE PROVIDE NAME AND DESCRIPTION FOR EACH RPC METHOD PARAMETER, "
229  "OR NAME, DESCRIPTION AND A CORRECTLY TYPED SAMPLE VALUE FOR EACH PARAMETER_____________");
230 }
231 
232 template<typename ARG, typename EXAMPLE>
234 {
235  static_assert(
236  isConstr<EXAMPLE, ARG>(),
237  "_____________THE DEDUCED TYPE OF A PARAMETER EXAMPLE CAN NOT BE USED TO "
238  "CONSTRUCT ITS FUNCTION PARAMETER IN CALL TO Reflector::method(). "
239  "PLEASE PROVIDE NAME AND DESCRIPTION FOR EACH RPC METHOD PARAMETER, "
240  "OR NAME, DESCRIPTION AND A CORRECTLY TYPED SAMPLE VALUE FOR EACH PARAMETER_____________");
241 }
242 
243 template<typename... Args, typename... Docs>
244 typename std::enable_if<((sizeof...(Args)) * 3 != sizeof...(Docs)) &&
245  ((sizeof...(Args)) * 2 != sizeof...(Docs))>::type
247 {
248  static_assert(sizeof(ArgumentTuple<Args...>*) == 0,
249  "_____________NUMBER OF NAMES/DESCRIPTIONS/SAMPLEVALUES FOR PARAMETERS "
250  "IN CALL TO Reflector::method() DOES NOT MATCH THE PROVIDED FUNCTION'S SIGNATURE. "
251  "PLEASE PROVIDE NAME AND DESCRIPTION FOR EACH RPC METHOD PARAMETER, "
252  "OR NAME, DESCRIPTION AND A CORRECTLY TYPED SAMPLE VALUE FOR EACH PARAMETER_____________");
253 }
254 
255 // should never happen
257 
258 template<typename HeadArg, typename... TailArgs, typename Name, typename Description, typename Example,
259  typename... TailDocs>
260 typename std::enable_if<(sizeof...(TailArgs)) * 3 == sizeof...(TailDocs)>::type
263 {
264  assertName<Name>();
265  assertDescription<Description>();
266  assertExample<HeadArg, Example>();
268 }
269 
270 template<typename HeadArg, typename... TailArgs, typename Name, typename Description,
271  typename... TailDocs>
272 typename std::enable_if<(sizeof...(TailArgs)) * 2 == sizeof...(TailDocs)>::type
275 {
276  assertName<Name>();
277  assertDescription<Description>();
279 }
280 
281 template<typename F, typename Comment, typename... Description>
282 constexpr typename std::enable_if<!FunctionTraits<F>::isFunction>::type invalidAssertion()
283 {
284  static_assert(sizeof(F*) == 0,
285  "_____________RECEIVED INVALID FUNCTION TYPE "
286  "IN CALL TO Reflector::method(). PLEASE PROVIDE A VALID FUNCTION OBJECT_____________");
287 }
288 
289 template<typename F, typename Comment, typename... Description>
290 constexpr typename std::enable_if<FunctionTraits<F>::isFunction>::type invalidAssertion()
291 {
292  static_assert(
293  Private::isConstr<Comment, std::string>(),
294  "_____________THE PROVIDED TYPE OF THE COMMENT CAN NOT BE USED TO INITIALIZE A "
295  "STRING IN CALL TO Reflector::method(). PLEASE PROVIDE A VALID TEXT DESCRIBING THE FUNCTION _____________");
297 }
298 
299 }; // namespace rpc
300 
302 
303 } // namespace Private
304 
305 
306 template<typename F, typename... Description>
307 using ValidRPCDescription = typename std::enable_if<Private::rpc::isValid<F, Description...>()>::type;
308 
309 template<typename F, typename... Description>
310 using InvalidRPCDescription = typename std::enable_if<!Private::rpc::isValid<F, Description...>()>::type;
311 
312 } // namespace mira
313 
314 #endif
void assertDescription()
Definition: RPCPatternCheck.h:222
static constexpr bool isConstr()
Definition: RPCPatternCheck.h:74
std::enable_if<((sizeof...(Args)) *3 !=sizeof...(Docs)) &&((sizeof...(Args)) *2 !=sizeof...(Docs))>::type patternError(ArgumentTuple< Args... > a, ArgumentTuple< Docs... > b)
Definition: RPCPatternCheck.h:246
typename InternalParser::Arguments Arguments
Definition: RPCPatternCheck.h:101
Definition: RPCPatternCheck.h:82
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
constexpr std::enable_if<((sizeof...(Args)) *3 !=sizeof...(Descriptions)) &&((sizeof...(Args)) *2 !=sizeof...(Descriptions)), bool >::type correctPattern(ArgumentTuple< Args... > a, ArgumentTuple< Descriptions... > b)
Definition: RPCPatternCheck.h:154
constexpr std::enable_if<!FunctionTraits< F >::isFunction, bool >::type isValid()
Definition: RPCPatternCheck.h:193
STL namespace.
R ReturnValue
Definition: RPCPatternCheck.h:125
static constexpr bool isFunction
Definition: RPCPatternCheck.h:91
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
typename std::enable_if< Private::rpc::isValid< F, Description... >()>::type ValidRPCDescription
Definition: RPCPatternCheck.h:307
typename std::enable_if<!Private::rpc::isValid< F, Description... >()>::type InvalidRPCDescription
Definition: RPCPatternCheck.h:310
void assertExample()
Definition: RPCPatternCheck.h:233
Definition: RPCPatternCheck.h:88
static constexpr bool value
Definition: RPCPatternCheck.h:69
void assertName()
Definition: RPCPatternCheck.h:211
Definition: RPCPatternCheck.h:58
constexpr std::enable_if<!FunctionTraits< F >::isFunction >::type invalidAssertion()
Definition: RPCPatternCheck.h:282
typename InternalParser::ReturnValue ReturnValue
Definition: RPCPatternCheck.h:100