]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/contract/core/specify.hpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / boost / contract / core / specify.hpp
1
2 #ifndef BOOST_CONTRACT_SPECIFY_HPP_
3 #define BOOST_CONTRACT_SPECIFY_HPP_
4
5 // Copyright (C) 2008-2018 Lorenzo Caminiti
6 // Distributed under the Boost Software License, Version 1.0 (see accompanying
7 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
8 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
9
10 /** @file
11 Specify preconditions, old value copies at body, postconditions, and exception
12 guarantees
13
14 Preconditions, old value copies at body, postconditions, and exception
15 guarantees are all optionals but, when they are specified, they need to be
16 specified in that order.
17 */
18
19 #include <boost/contract/core/config.hpp>
20 #include <boost/contract/detail/decl.hpp>
21 #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
22 defined(BOOST_CONTRACT_STATIC_LINK)
23 #include <boost/contract/detail/condition/cond_base.hpp>
24 #include <boost/contract/detail/condition/cond_post.hpp>
25 #include <boost/contract/detail/auto_ptr.hpp>
26 #include <boost/contract/detail/none.hpp>
27 #endif
28 #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
29 !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
30 !defined(BOOST_CONTRACT_NO_EXCEPTS)
31 #include <boost/contract/detail/debug.hpp>
32 #endif
33 #include <boost/config.hpp>
34
35 // NOTE: No inheritance for faster run-times (macros to avoid duplicated code).
36
37 /* PRIVATE */
38
39 /* @cond */
40
41 // NOTE: Private copy ops below will force compile-time error is `auto c = ...`
42 // is used instead of `check c = ...` but only up to C++17. C++17 strong copy
43 // elision on function return values prevents this lib from generating a
44 // compile-time error in those cases, but the lib will still generate a run-time
45 // error according with ON_MISSING_CHECK_DECL.
46 #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
47 defined(BOOST_CONTRACT_STATIC_LINK)
48 #define BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(class_type, cond_type) \
49 private: \
50 boost::contract::detail::auto_ptr<cond_type > cond_; \
51 explicit class_type(cond_type* cond) : cond_(cond) {} \
52 class_type(class_type const& other) : cond_(other.cond_) {} \
53 class_type& operator=(class_type const& other) { \
54 cond_ = other.cond_; \
55 return *this; \
56 }
57
58 #define BOOST_CONTRACT_SPECIFY_COND_RELEASE_ cond_.release()
59 #else
60 #define BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(class_type, cond_type) \
61 private: \
62 class_type() {} \
63 class_type(class_type const&) {} \
64 class_type& operator=(class_type const&) { return *this; }
65
66 #define BOOST_CONTRACT_SPECIFY_COND_RELEASE_ /* nothing */
67 #endif
68
69 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
70 #define BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_ \
71 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
72 cond_->set_pre(f); \
73 return specify_old_postcondition_except<VirtualResult>( \
74 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
75 #else
76 #define BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_ \
77 return specify_old_postcondition_except<VirtualResult>( \
78 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
79 #endif
80
81 #ifndef BOOST_CONTRACT_NO_OLDS
82 #define BOOST_CONTRACT_SPECIFY_OLD_IMPL_ \
83 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
84 cond_->set_old(f); \
85 return specify_postcondition_except<VirtualResult>( \
86 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
87 #else
88 #define BOOST_CONTRACT_SPECIFY_OLD_IMPL_ \
89 return specify_postcondition_except<VirtualResult>( \
90 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
91 #endif
92
93 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
94 #define BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_ \
95 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
96 cond_->set_post(f); \
97 return specify_except(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
98 #else
99 #define BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_ \
100 return specify_except(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
101 #endif
102
103 #ifndef BOOST_CONTRACT_NO_EXCEPTS
104 #define BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ \
105 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
106 cond_->set_except(f); \
107 return specify_nothing(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
108 #else
109 #define BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ \
110 return specify_nothing(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
111 #endif
112
113 /* @endcond */
114
115 /* CODE */
116
117 namespace boost {
118 namespace contract {
119 class virtual_;
120
121 template<typename VR>
122 class specify_precondition_old_postcondition_except;
123
124 template<typename VR>
125 class specify_old_postcondition_except;
126
127 template<typename VR>
128 class specify_postcondition_except;
129
130 class specify_except;
131 }
132 }
133
134 namespace boost { namespace contract {
135
136 /**
137 Used to prevent setting other contract conditions after exception guarantees.
138
139 This class has no member function so it is used to prevent specifying additional
140 functors to check any other contract.
141 This object is internally constructed by this library when users specify
142 contracts calling @RefFunc{boost::contract::function} and similar functions
143 (that is why this class does not have a public constructor).
144
145 @see @RefSect{tutorial, Tutorial}
146 */
147 class specify_nothing { // Privately copyable (as *).
148 public:
149 /**
150 Destruct this object.
151
152 @b Throws: This can throw in case programmers specify failure handlers that
153 throw exceptions instead of terminating the program (see
154 @RefSect{advanced.throw_on_failures__and__noexcept__,
155 Throw on Failure}).
156 (This is declared @c noexcept(false) since C++11.)
157 */
158 ~specify_nothing() BOOST_NOEXCEPT_IF(false) {}
159
160 // No set member function here.
161
162 /** @cond */
163 private:
164 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(specify_nothing,
165 boost::contract::detail::cond_base)
166
167 // Friends (used to limit library's public API).
168
169 friend class check;
170
171 template<typename VR>
172 friend class specify_precondition_old_postcondition_except;
173
174 template<typename VR>
175 friend class specify_old_postcondition_except;
176
177 template<typename VR>
178 friend class specify_postcondition_except;
179
180 friend class specify_except;
181 /** @endcond */
182 };
183
184 /**
185 Allow to specify exception guarantees.
186
187 Allow to specify the functor this library will call to check exception
188 guarantees.
189 This object is internally constructed by this library when users specify
190 contracts calling @RefFunc{boost::contract::function} and similar functions
191 (that is why this class does not have a public constructor).
192
193 @see @RefSect{tutorial.exception_guarantees, Exception Guarantees}
194 */
195 class specify_except { // Privately copyable (as *).
196 public:
197 /**
198 Destruct this object.
199
200 @b Throws: This can throw in case programmers specify failure handlers that
201 throw exceptions instead of terminating the program (see
202 @RefSect{advanced.throw_on_failures__and__noexcept__,
203 Throw on Failure}).
204 (This is declared @c noexcept(false) since C++11.)
205 */
206 ~specify_except() BOOST_NOEXCEPT_IF(false) {}
207
208 /**
209 Allow to specify exception guarantees.
210
211 @param f Nullary functor called by this library to check exception
212 guarantees @c f().
213 Assertions within this functor are usually programmed using
214 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
215 call to this functor indicates a contract assertion failure (and
216 will result in this library calling
217 @RefFunc{boost::contract::except_failure}).
218 This functor should capture variables by (constant) references
219 (to access the values they will have at function exit).
220
221 @return After exception guarantees have been specified, the object returned
222 by this function does not allow to specify any additional contract.
223 */
224 template<typename F>
225 specify_nothing except(F const& f) {
226 BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
227 }
228
229 /** @cond */
230 private:
231 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(specify_except,
232 boost::contract::detail::cond_base)
233
234 // Friends (used to limit library's public API).
235
236 friend class check;
237
238 template<typename VR>
239 friend class specify_precondition_old_postcondition_except;
240
241 template<typename VR>
242 friend class specify_old_postcondition_except;
243
244 template<typename VR>
245 friend class specify_postcondition_except;
246 /** @endcond */
247 };
248
249 /**
250 Allow to specify postconditions or exception guarantees.
251
252 Allow to specify functors this library will call to check postconditions or
253 exception guarantees.
254 This object is internally constructed by this library when users specify
255 contracts calling @RefFunc{boost::contract::function} and similar functions
256 (that is why this class does not have a public constructor).
257
258 @see @RefSect{tutorial.postconditions, Postconditions},
259 @RefSect{tutorial.exception_guarantees, Exception Guarantees}
260
261 @tparam VirtualResult Return type of the enclosing function declaring the
262 contract if that function is either a virtual public
263 function or a public function override.
264 Otherwise, this type is always @c void.
265 */
266 template<typename VirtualResult = void>
267 class specify_postcondition_except { // Privately copyable (as *).
268 public:
269 /**
270 Destruct this object.
271
272 @b Throws: This can throw in case programmers specify failure handlers that
273 throw exceptions instead of terminating the program (see
274 @RefSect{advanced.throw_on_failures__and__noexcept__,
275 Throw on Failure}).
276 (This is declared @c noexcept(false) since C++11.)
277 */
278 ~specify_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
279
280 /**
281 Allow to specify postconditions.
282
283 @param f Functor called by this library to check postconditions
284 @c f(...).
285 Assertions within this functor are usually programmed using
286 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
287 call to this functor indicates a contract assertion failure (and
288 will result in this library calling
289 @RefFunc{boost::contract::postcondition_failure}).
290 This functor should capture variables by (constant) references
291 (to access the values they will have at function exit).
292 This functor must be a nullary functor if @c VirtualResult is
293 @c void, otherwise it must be a unary functor accepting the
294 return value as a parameter of type <c>VirtualResult const&</c>
295 (to avoid extra copies of the return value, or of type
296 @c VirtualResult or <c>VirtualResult const</c> if extra copies
297 of the return value are irrelevant).
298
299 @return After postconditions have been specified, the object returned by
300 this function allows to optionally specify exception guarantees.
301 */
302 template<typename F>
303 specify_except postcondition(F const& f) {
304 BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
305 }
306
307 /**
308 Allow to specify exception guarantees.
309
310 @param f Nullary functor called by this library to check exception
311 guarantees @c f().
312 Assertions within this functor are usually programmed using
313 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
314 call to this functor indicates a contract assertion failure (and
315 will result in this library calling
316 @RefFunc{boost::contract::except_failure}).
317 This functor should capture variables by (constant) references
318 (to access the values they will have at function exit).
319
320 @return After exception guarantees have been specified, the object returned
321 by this function does not allow to specify any additional contract.
322 */
323 template<typename F>
324 specify_nothing except(F const& f) {
325 BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
326 }
327
328 /** @cond */
329 private:
330 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
331 specify_postcondition_except,
332 boost::contract::detail::cond_post<typename
333 boost::contract::detail::none_if_void<VirtualResult>::type>
334 )
335
336 // Friends (used to limit library's public API).
337
338 friend class check;
339 friend class specify_precondition_old_postcondition_except<VirtualResult>;
340 friend class specify_old_postcondition_except<VirtualResult>;
341 /** @endcond */
342 };
343
344 /**
345 Allow to specify old value copies at body, postconditions, and exception
346 guarantees.
347
348 Allow to specify functors this library will call to copy old value at body,
349 check postconditions, and check exception guarantees.
350 This object is internally constructed by this library when users specify
351 contracts calling @RefFunc{boost::contract::function} and similar functions
352 (that is why this class does not have a public constructor).
353
354 @see @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body},
355 @RefSect{tutorial.postconditions, Postconditions},
356 @RefSect{tutorial.exception_guarantees, Exception Guarantees}
357
358 @tparam VirtualResult Return type of the enclosing function declaring the
359 contract if that function is either a virtual public
360 function or a public function override.
361 Otherwise, this type is always @c void.
362 */
363 template<typename VirtualResult = void>
364 class specify_old_postcondition_except { // Privately copyable (as *).
365 public:
366 /**
367 Destruct this object.
368
369 @b Throws: This can throw in case programmers specify failure handlers that
370 throw exceptions instead of terminating the program (see
371 @RefSect{advanced.throw_on_failures__and__noexcept__,
372 Throw on Failure}).
373 (This is declared @c noexcept(false) since C++11.)
374 */
375 ~specify_old_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
376
377 /**
378 Allow to specify old value copies at body.
379
380 It should often be sufficient to initialize old value pointers as soon as
381 they are declared, without using this function (see
382 @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body}).
383
384 @param f Nullary functor called by this library @c f() to assign old
385 value copies just before the body is executed but after entry
386 invariants (when they apply) and preconditions are checked.
387 Old value pointers within this functor call are usually assigned
388 using @RefMacro{BOOST_CONTRACT_OLDOF}.
389 Any exception thrown by a call to this functor will result in
390 this library calling @RefFunc{boost::contract::old_failure}
391 (because old values could not be copied to check postconditions
392 and exception guarantees).
393 This functor should capture old value pointers by references so
394 they can be assigned (all other variables needed to evaluate old
395 value expressions can be captured by (constant) value, or better
396 by (constant) reference to avoid extra copies).
397
398 @return After old value copies at body have been specified, the object
399 returned by this function allows to optionally specify
400 postconditions and exception guarantees.
401 */
402 template<typename F>
403 specify_postcondition_except<VirtualResult> old(F const& f) {
404 BOOST_CONTRACT_SPECIFY_OLD_IMPL_
405 }
406
407 /**
408 Allow to specify postconditions.
409
410 @param f Functor called by this library to check postconditions
411 @c f(...).
412 Assertions within this functor are usually programmed using
413 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
414 call to this functor indicates a contract assertion failure (and
415 will result in this library calling
416 @RefFunc{boost::contract::postcondition_failure}).
417 This functor should capture variables by (constant) references
418 (to access the values they will have at function exit).
419 This functor must be a nullary functor if @c VirtualResult is
420 @c void, otherwise it must be a unary functor accepting the
421 return value as a parameter of type <c>VirtualResult const&</c>
422 (to avoid extra copies of the return value, or of type
423 @c VirtualResult or <c>VirtualResult const</c> if extra copies
424 of the return value are irrelevant).
425
426 @return After postconditions have been specified, the object returned by
427 this function allows to optionally specify exception guarantees.
428 */
429 template<typename F>
430 specify_except postcondition(F const& f) {
431 BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
432 }
433
434 /**
435 Allow to specify exception guarantees.
436
437 @param f Nullary functor called by this library to check exception
438 guarantees @c f().
439 Assertions within this functor are usually programmed using
440 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
441 call to this functor indicates a contract assertion failure (and
442 will result in this library calling
443 @RefFunc{boost::contract::except_failure}).
444 This functor should capture variables by (constant) references
445 (to access the values they will have at function exit).
446
447 @return After exception guarantees have been specified, the object returned
448 by this function does not allow to specify any additional contract.
449 */
450 template<typename F>
451 specify_nothing except(F const& f) {
452 BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
453 }
454
455 /** @cond */
456 private:
457 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
458 specify_old_postcondition_except,
459 boost::contract::detail::cond_post<typename
460 boost::contract::detail::none_if_void<VirtualResult>::type>
461 )
462
463 // Friends (used to limit library's public API).
464
465 friend class check;
466 friend class specify_precondition_old_postcondition_except<VirtualResult>;
467
468 template<class C>
469 friend specify_old_postcondition_except<> constructor(C*);
470
471 template<class C>
472 friend specify_old_postcondition_except<> destructor(C*);
473 /** @endcond */
474 };
475
476 /**
477 Allow to specify preconditions, old value copies at body, postconditions, and
478 exception guarantees.
479
480 Allow to specify functors this library will call to check preconditions, copy
481 old values at body, check postconditions, and check exception guarantees.
482 This object is internally constructed by this library when users specify
483 contracts calling @RefFunc{boost::contract::function} and similar functions
484 (that is why this class does not have a public constructor).
485
486 @see @RefSect{tutorial.preconditions, Preconditions},
487 @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body},
488 @RefSect{tutorial.postconditions, Postconditions},
489 @RefSect{tutorial.exception_guarantees, Exception Guarantees}
490
491 @tparam VirtualResult Return type of the enclosing function declaring the
492 contract if that function is either a virtual public
493 function or a public function override.
494 Otherwise, this type is always @c void.
495 */
496 template<
497 typename VirtualResult /* = void (already in fwd decl from decl.hpp) */
498 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
499 = void
500 #endif
501 >
502 class specify_precondition_old_postcondition_except { // Priv. copyable (as *).
503 public:
504 /**
505 Destruct this object.
506
507 @b Throws: This can throw in case programmers specify failure handlers that
508 throw exceptions instead of terminating the program (see
509 @RefSect{advanced.throw_on_failures__and__noexcept__,
510 Throw on Failure}).
511 (This is declared @c noexcept(false) since C++11.)
512 */
513 ~specify_precondition_old_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
514
515 /**
516 Allow to specify preconditions.
517
518 @param f Nullary functor called by this library to check preconditions
519 @c f().
520 Assertions within this functor are usually programmed using
521 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
522 call to this functor indicates a contract assertion failure (and
523 will result in this library calling
524 @RefFunc{boost::contract::precondition_failure}).
525 This functor should capture variables by (constant) value, or
526 better by (constant) reference (to avoid extra copies).
527
528 @return After preconditions have been specified, the object returned by this
529 function allows to optionally specify old value copies at body,
530 postconditions, and exception guarantees.
531 */
532 template<typename F>
533 specify_old_postcondition_except<VirtualResult> precondition(F const& f) {
534 BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_
535 }
536
537 /**
538 Allow to specify old value copies at body.
539
540 It should often be sufficient to initialize old value pointers as soon as
541 they are declared, without using this function (see
542 @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body}).
543
544 @param f Nullary functor called by this library @c f() to assign old
545 value copies just before the body is executed but after entry
546 invariants (when they apply) and preconditions are checked.
547 Old value pointers within this functor call are usually assigned
548 using @RefMacro{BOOST_CONTRACT_OLDOF}.
549 Any exception thrown by a call to this functor will result in
550 this library calling @RefFunc{boost::contract::old_failure}
551 (because old values could not be copied to check postconditions
552 and exception guarantees).
553 This functor should capture old value pointers by references so
554 they can be assigned (all other variables needed to evaluate old
555 value expressions can be captured by (constant) value, or better
556 by (constant) reference to avoid extra copies).
557
558 @return After old value copies at body have been specified, the object
559 returned by this functions allows to optionally specify
560 postconditions and exception guarantees.
561 */
562 template<typename F>
563 specify_postcondition_except<VirtualResult> old(F const& f) {
564 BOOST_CONTRACT_SPECIFY_OLD_IMPL_
565 }
566
567 /**
568 Allow to specify postconditions.
569
570 @param f Functor called by this library to check postconditions
571 @c f(...).
572 Assertions within this functor are usually programmed using
573 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
574 call to this functor indicates a contract assertion failure (and
575 will result in this library calling
576 @RefFunc{boost::contract::postcondition_failure}).
577 This functor should capture variables by (constant) references
578 (to access the values they will have at function exit).
579 This functor must be a nullary functor if @c VirtualResult is
580 @c void, otherwise it must be a unary functor accepting the
581 return value as a parameter of type <c>VirtualResult const&</c>
582 (to avoid extra copies of the return value, or of type
583 @c VirtualResult or <c>VirtualResult const</c> if extra copies
584 of the return value are irrelevant).
585
586 @return After postconditions have been specified, the object returned by
587 this function allows to optionally specify exception guarantees.
588 */
589 template<typename F>
590 specify_except postcondition(F const& f) {
591 BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
592 }
593
594 /**
595 Allow to specify exception guarantees.
596
597 @param f Nullary functor called by this library to check exception
598 guarantees @c f().
599 Assertions within this functor are usually programmed using
600 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
601 call to this functor indicates a contract assertion failure (and
602 will result in this library calling
603 @RefFunc{boost::contract::except_failure}).
604 This functor should capture variables by (constant) references
605 (to access the values they will have at function exit).
606
607 @return After exception guarantees have been specified, the object returned
608 by this function does not allow to specify any additional contract.
609 */
610 template<typename F>
611 specify_nothing except(F const& f) {
612 BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
613 }
614
615 /** @cond */
616 private:
617 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
618 specify_precondition_old_postcondition_except,
619 boost::contract::detail::cond_post<typename
620 boost::contract::detail::none_if_void<VirtualResult>::type>
621 )
622
623 // Friends (used to limit library's public API).
624
625 friend class check;
626 friend specify_precondition_old_postcondition_except<> function();
627
628 template<class C>
629 friend specify_precondition_old_postcondition_except<> public_function();
630
631 template<class C>
632 friend specify_precondition_old_postcondition_except<> public_function(C*);
633
634 template<class C>
635 friend specify_precondition_old_postcondition_except<> public_function(
636 virtual_*, C*);
637
638 template<typename VR, class C>
639 friend specify_precondition_old_postcondition_except<VR> public_function(
640 virtual_*, VR&, C*);
641
642 BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(1,
643 O, VR, F, C, Args, v, r, f, obj, args)
644 /** @endcond */
645 };
646
647 } } // namespace
648
649 #endif // #include guard
650