Line data Source code
1 : /** 2 : * \file 3 : * Implements the "Safe Bool" idiom, which is a safer alternative to operator 4 : * bool. Based on: 5 : * https://www.artima.com/articles/the-safe-bool-idiom 6 : * TLDR: We may want to be able to use `operator bool()` to check an object's 7 : * abstract truthfulness using `if (object) {...}`, but that opens up implicit 8 : * casting and comparisons that come with the bool type that are almost 9 : * certainly not desired, like `int count = object`. This is achieved via the 10 : * BoolType function pointer which isn't actually called, but is the only 11 : * boolean-ish thing the type can be implicitly converted to using the BoolType 12 : * operator. 13 : * 14 : * If you want the boolean test function to be virtual, implement it as: 15 : * virtual bool boolean_test() const; 16 : * and derive the class from SafeBool_T with no template argument: 17 : * class YourClass : public SafeBool_T<>. 18 : * 19 : * If you do NOT want the boolean test function to be virtual, implement it as: 20 : * bool boolean_test() const; 21 : * and derive the class from SafeBool_T with the class as the template argument: 22 : * class YourClass : public SafeBool_T<YourClass>. 23 : */ 24 : 25 : #ifndef OPENDDS_DCPS_SAFE_BOOL_T_H 26 : #define OPENDDS_DCPS_SAFE_BOOL_T_H 27 : 28 : #include <dds/Versioned_Namespace.h> 29 : 30 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 31 : 32 : namespace OpenDDS { 33 : namespace DCPS { 34 : 35 : class SafeBoolBase { 36 : public: 37 : typedef void (SafeBoolBase::*BoolType)() const; 38 0 : void this_type_does_not_support_comparisons() const {} 39 : 40 : protected: 41 2904 : SafeBoolBase() {} 42 870 : SafeBoolBase(const SafeBoolBase&) {} 43 764 : SafeBoolBase& operator=(const SafeBoolBase&) {return *this;} 44 3774 : ~SafeBoolBase() {} 45 : }; 46 : 47 : template <typename DerivedNonVirtual = void> 48 : class SafeBool_T : public SafeBoolBase { 49 : public: 50 93 : operator BoolType() const 51 : { 52 93 : return (static_cast<const DerivedNonVirtual*>(this))->boolean_test() 53 93 : ? &SafeBoolBase::this_type_does_not_support_comparisons : 0; 54 : } 55 : 56 : protected: 57 3772 : ~SafeBool_T() {} 58 : }; 59 : 60 : template<> 61 : class SafeBool_T<void> : public SafeBoolBase { 62 : public: 63 3 : operator BoolType() const 64 : { 65 3 : return boolean_test() ? 66 3 : &SafeBoolBase::this_type_does_not_support_comparisons : 0; 67 : } 68 : 69 : protected: 70 : virtual bool boolean_test() const = 0; 71 2 : virtual ~SafeBool_T() {} 72 : }; 73 : 74 : template <typename X, typename Y> 75 : bool operator==(const SafeBool_T<X>& x, const SafeBool_T<Y>&) 76 : { 77 : x.this_type_does_not_support_comparisons(); 78 : return false; 79 : } 80 : 81 : template <typename X, typename Y> 82 : bool operator!=(const SafeBool_T<X>& x, const SafeBool_T<Y>&) 83 : { 84 : x.this_type_does_not_support_comparisons(); 85 : return false; 86 : } 87 : 88 : } // namespace DCPS 89 : } // namespace OpenDDS 90 : 91 : OPENDDS_END_VERSIONED_NAMESPACE_DECL 92 : 93 : #endif