// bsltf_evilbooleantype.h -*-C++-*- #ifndef INCLUDED_BSLTF_EVILBOOLEANTYPE #define INCLUDED_BSLTF_EVILBOOLEANTYPE #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide the most awkward type that is convertible to 'bool'. // //@CLASSES: // bsltf::EvilBooleanType: most awkward type that is convertible to 'bool' // //@SEE_ALSO: bsltf_templatetestfacility // //@DESCRIPTION: This component provides a type that is convertible-to-'bool', // and so may be used to satisfy many C++ standard library requirements, but is // perversely implemented to provide the most awkward interface that meets the // requirements. This type is not intended for use in production code, but is // most useful when implementing test drivers for generic components that must // accept predicates, or other expressions, that yield a type that is merely // convertible to 'bool'. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Basic Syntax ///- - - - - - - - - - - - // The following snippets of code provide a simple illustration of using // 'bsltf::EvilBooleanType'. // // First, we create an object 'trueValue' and initialize it with the 'true' // value: //.. // bsltf::EvilBooleanType trueValue(true); //.. // Now, we can use it for if-else conditions or another constructions, that // require boolen value: //.. // if (trueValue) { // assert(trueValue); // } //.. // Finally we create another object, having the opposite value, and verify it: //.. // bsltf::EvilBooleanType falseValue = !trueValue; // assert(false == (bool)falseValue); //.. #include <bslscm_version.h> #include <bsls_keyword.h> namespace BloombergLP { namespace bsltf { // ===================== // class EvilBooleanType // ===================== struct EvilBooleanType { // This class provides a test type for predicates returning a type that is // convertible-to-bool. It makes life reasonably difficult by disabling // the address-of and comma operators, but deliberately does not overload // the '&&' and '||' operators, as we hope the standard will be updated to // no longer require such support. Once C++11 becomes available, this // class would use an 'explicit operator bool()' conversion operator, and // explicitly supply the '==' and '!=' operators, but we use the // convertible-to-pointer-to-member idiom in the meantime. Implicitly // defined operations fill out the API as needed. private: // PRIVATE TYPES struct ImpDetail // Struct, containing value to be pointed to. { int d_member; }; typedef int ImpDetail::* BoolResult; // Typedef for pointer to the nested class field, that can be converted // to boolean. // DATA BoolResult d_value; // pointer being converted to boolean value private: // NOT IMPLEMENTED void operator=(const EvilBooleanType&) BSLS_KEYWORD_DELETED; void operator&() const BSLS_KEYWORD_DELETED; template<class T> void operator,(T&) const BSLS_KEYWORD_DELETED; public: // CREATORS EvilBooleanType(bool value); // IMPLICIT // Create a 'EvilBooleanType' object having the attribute value defined // by the specified 'value'. #ifdef BSLS_COMPILERFEATURES_SUPPORT_DEFAULTED_FUNCTIONS // To avoid warnings about future incompatibility due to the deleted copy // assignment operator we declare the copy constructor as implicitly // generated. For consistency the destructor was also placed here and // declared to be explicitly generated. EvilBooleanType(const EvilBooleanType& original) = default; // Create a 'EvilBooleanType' object having the same value as the // specified 'original' object. ~EvilBooleanType() = default; // Destroy this object. #endif // ACCESSORS operator BoolResult() const; // Return the value of this object. EvilBooleanType operator!() const; // Return the newly created object having the logically negated value // of this object. }; EvilBooleanType operator==(const EvilBooleanType& lhs, const EvilBooleanType& rhs); // Return an 'EvilBoolanType' value that converts to 'true' if the // specified 'lhs' and 'rhs' have the same value, and a value that converts // to 'false' otherwise. Two 'EvilBooleanType' objects have the same value // if the values resulting from converting each to 'bool' have the same // value. EvilBooleanType operator!=(const EvilBooleanType& lhs, const EvilBooleanType& rhs); // Return an 'EvilBoolanType' value that converts to 'true' if the // specified 'lhs' and 'rhs' do not have the same value, and a value that // converts to 'false' otherwise. Two 'EvilBooleanType' objects do not have // the same value if the values resulting from converting each to 'bool' do // not have the same value. // ============================================================================ // INLINE AND TEMPLATE FUNCTION IMPLEMENTATIONS // ============================================================================ // --------------------- // class EvilBooleanType // --------------------- // CREATORS inline EvilBooleanType::EvilBooleanType(bool value) : d_value(!value ? 0 : &ImpDetail::d_member) { } // ACCESSORS inline EvilBooleanType::operator BoolResult() const { return d_value; } inline EvilBooleanType EvilBooleanType::operator!() const { return !d_value; } } // close package namespace inline bsltf::EvilBooleanType bsltf::operator==(const EvilBooleanType& lhs, const EvilBooleanType& rhs) { return static_cast<bool>(lhs) == static_cast<bool>(rhs); } inline bsltf::EvilBooleanType bsltf::operator!=(const EvilBooleanType& lhs, const EvilBooleanType& rhs) { return static_cast<bool>(lhs) != static_cast<bool>(rhs); } } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2013 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------