Dependents:   sensomed

Committer:
switches
Date:
Tue Nov 08 18:27:11 2016 +0000
Revision:
0:0e018d759a2a
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
switches 0:0e018d759a2a 1 /* mbed Microcontroller Library
switches 0:0e018d759a2a 2 * Copyright (c) 2006-2013 ARM Limited
switches 0:0e018d759a2a 3 *
switches 0:0e018d759a2a 4 * Licensed under the Apache License, Version 2.0 (the "License");
switches 0:0e018d759a2a 5 * you may not use this file except in compliance with the License.
switches 0:0e018d759a2a 6 * You may obtain a copy of the License at
switches 0:0e018d759a2a 7 *
switches 0:0e018d759a2a 8 * http://www.apache.org/licenses/LICENSE-2.0
switches 0:0e018d759a2a 9 *
switches 0:0e018d759a2a 10 * Unless required by applicable law or agreed to in writing, software
switches 0:0e018d759a2a 11 * distributed under the License is distributed on an "AS IS" BASIS,
switches 0:0e018d759a2a 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
switches 0:0e018d759a2a 13 * See the License for the specific language governing permissions and
switches 0:0e018d759a2a 14 * limitations under the License.
switches 0:0e018d759a2a 15 */
switches 0:0e018d759a2a 16
switches 0:0e018d759a2a 17 #ifndef BLE_API_SAFE_BOOL_H_
switches 0:0e018d759a2a 18 #define BLE_API_SAFE_BOOL_H_
switches 0:0e018d759a2a 19
switches 0:0e018d759a2a 20 /* Safe bool idiom, see : http://www.artima.com/cppsource/safebool.html */
switches 0:0e018d759a2a 21
switches 0:0e018d759a2a 22 namespace SafeBool_ {
switches 0:0e018d759a2a 23 /**
switches 0:0e018d759a2a 24 * @brief Base class for all intances of SafeBool.
switches 0:0e018d759a2a 25 * This base class reduces instantiation of trueTag function.
switches 0:0e018d759a2a 26 */
switches 0:0e018d759a2a 27 class base {
switches 0:0e018d759a2a 28 template<typename>
switches 0:0e018d759a2a 29 friend class SafeBool;
switches 0:0e018d759a2a 30
switches 0:0e018d759a2a 31 protected:
switches 0:0e018d759a2a 32 /**
switches 0:0e018d759a2a 33 * The bool type is a pointer to method which can be used in boolean context.
switches 0:0e018d759a2a 34 */
switches 0:0e018d759a2a 35 typedef void (base::*BoolType_t)() const;
switches 0:0e018d759a2a 36
switches 0:0e018d759a2a 37 /**
switches 0:0e018d759a2a 38 * Non implemented call, use to disallow conversion between unrelated types.
switches 0:0e018d759a2a 39 */
switches 0:0e018d759a2a 40 void invalidTag() const;
switches 0:0e018d759a2a 41
switches 0:0e018d759a2a 42 /**
switches 0:0e018d759a2a 43 * Member function which indicate true value.
switches 0:0e018d759a2a 44 */
switches 0:0e018d759a2a 45 void trueTag() const {}
switches 0:0e018d759a2a 46 };
switches 0:0e018d759a2a 47
switches 0:0e018d759a2a 48
switches 0:0e018d759a2a 49 }
switches 0:0e018d759a2a 50
switches 0:0e018d759a2a 51 /**
switches 0:0e018d759a2a 52 * @brief template class SafeBool use CRTP to made boolean conversion easy and correct.
switches 0:0e018d759a2a 53 * Derived class should implement the function bool toBool() const to make this work. Inheritance
switches 0:0e018d759a2a 54 * should be public.
switches 0:0e018d759a2a 55 *
switches 0:0e018d759a2a 56 * @tparam T Type of the derived class
switches 0:0e018d759a2a 57 *
switches 0:0e018d759a2a 58 * @code
switches 0:0e018d759a2a 59 *
switches 0:0e018d759a2a 60 * class A : public SafeBool<A> {
switches 0:0e018d759a2a 61 * public:
switches 0:0e018d759a2a 62 *
switches 0:0e018d759a2a 63 * // boolean conversion
switches 0:0e018d759a2a 64 * bool toBool() {
switches 0:0e018d759a2a 65 *
switches 0:0e018d759a2a 66 * }
switches 0:0e018d759a2a 67 * };
switches 0:0e018d759a2a 68 *
switches 0:0e018d759a2a 69 * class B : public SafeBool<B> {
switches 0:0e018d759a2a 70 * public:
switches 0:0e018d759a2a 71 *
switches 0:0e018d759a2a 72 * // boolean conversion
switches 0:0e018d759a2a 73 * bool toBool() const {
switches 0:0e018d759a2a 74 *
switches 0:0e018d759a2a 75 * }
switches 0:0e018d759a2a 76 * };
switches 0:0e018d759a2a 77 *
switches 0:0e018d759a2a 78 * A a;
switches 0:0e018d759a2a 79 * B b;
switches 0:0e018d759a2a 80 *
switches 0:0e018d759a2a 81 * // will compile
switches 0:0e018d759a2a 82 * if(a) {
switches 0:0e018d759a2a 83 *
switches 0:0e018d759a2a 84 * }
switches 0:0e018d759a2a 85 *
switches 0:0e018d759a2a 86 * // compilation error
switches 0:0e018d759a2a 87 * if(a == b) {
switches 0:0e018d759a2a 88 *
switches 0:0e018d759a2a 89 * }
switches 0:0e018d759a2a 90 *
switches 0:0e018d759a2a 91 *
switches 0:0e018d759a2a 92 * @endcode
switches 0:0e018d759a2a 93 */
switches 0:0e018d759a2a 94 template <typename T>
switches 0:0e018d759a2a 95 class SafeBool : public SafeBool_::base {
switches 0:0e018d759a2a 96 public:
switches 0:0e018d759a2a 97 /**
switches 0:0e018d759a2a 98 * Bool operator implementation, derived class has to provide bool toBool() const function.
switches 0:0e018d759a2a 99 */
switches 0:0e018d759a2a 100 operator BoolType_t() const {
switches 0:0e018d759a2a 101 return (static_cast<const T*>(this))->toBool()
switches 0:0e018d759a2a 102 ? &SafeBool<T>::trueTag : 0;
switches 0:0e018d759a2a 103 }
switches 0:0e018d759a2a 104 };
switches 0:0e018d759a2a 105
switches 0:0e018d759a2a 106 /**
switches 0:0e018d759a2a 107 * Avoid conversion to bool between different classes.
switches 0:0e018d759a2a 108 */
switches 0:0e018d759a2a 109 template <typename T, typename U>
switches 0:0e018d759a2a 110 void operator==(const SafeBool<T>& lhs,const SafeBool<U>& rhs) {
switches 0:0e018d759a2a 111 lhs.invalidTag();
switches 0:0e018d759a2a 112 // return false;
switches 0:0e018d759a2a 113 }
switches 0:0e018d759a2a 114
switches 0:0e018d759a2a 115 /**
switches 0:0e018d759a2a 116 * Avoid conversion to bool between different classes.
switches 0:0e018d759a2a 117 */
switches 0:0e018d759a2a 118 template <typename T,typename U>
switches 0:0e018d759a2a 119 void operator!=(const SafeBool<T>& lhs,const SafeBool<U>& rhs) {
switches 0:0e018d759a2a 120 lhs.invalidTag();
switches 0:0e018d759a2a 121 // return false;
switches 0:0e018d759a2a 122 }
switches 0:0e018d759a2a 123
switches 0:0e018d759a2a 124 #endif /* BLE_API_SAFE_BOOL_H_ */