// bslalg_functoradapter.h -*-C++-*- #ifndef INCLUDED_BSLALG_FUNCTORADAPTER #define INCLUDED_BSLALG_FUNCTORADAPTER #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide an utility that adapts callable objects to functors. // //@CLASSES: // bslalg::FunctorAdapter: utility for using callable objects as functors // //@SEE_ALSO: bslstl_setcomparator, bslstl_mapcomparator // //@DESCRIPTION: This component provides a single utility template, // 'FunctorAdapter', that adapts a parameterized adaptee type, which can be any // callable object type, to a target functor type. This adaptation enables a // client to inherit from the target functor type even if the adaptee callable // object type is a function pointer type. This is particularly useful if the // client of the callable object type wants to take advantage of the empty-base // optimization to avoid paying storage cost when the callable object type is a // functor type with no data members. // // 'FunctorAdapter' defines an alias to the target functor type. If the // adaptee type is a functor type, the target type is an alias to the adaptee // type. If the adaptee type is a function pointer type, the target type is a // functor type that delegates to a function referred to by a function pointer // of the adaptee type. // ///Usage ///----- // This section illustrates the intended use of this component. // ///Example 1: Using function pointer base for an empty-base optimized class /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Suppose that we wanted to define a binder that binds a binary predicate of a // parameterized type to a value passed on construction. Also suppose that we // wanted to use the empty-base optimization to avoid paying storage cost when // the predicate type is a functor type with no data members. Unfortunately, // the binary predicate type may be a function pointer type, which cannot serve // as a base class. The solution is to have the binder inherit from // 'FunctorAdapter::Type', which adapts a function pointer type to a functor // type that is a suitable base class. // // First, we define the class 'Bind2ndInteger', which inherits from // 'FunctorAdapter::Type' to take advantage of the empty-base optimization: //.. // template <class BINARY_PREDICATE> // class Bind2ndInteger : private FunctorAdapter<BINARY_PREDICATE>::Type { // // This class provides a functor that delegate its function-call // // operator to the parameterized 'BINARY_PREDICATE', passing the user // // supplied parameter as the first argument and the integer value // // passed on construction as the second argument. // // // DATA // int d_bondValue; // the bound value // // // NOT IMPLEMENTED // Bind2ndInteger(const Bind2ndInteger&); // Bind2ndInteger& operator=(const Bind2ndInteger&); // // public: // // CREATORS // Bind2ndInteger(int value, const BINARY_PREDICATE& predicate); // // Create a 'Bind2ndInteger' object that will bind the second // // parameter of the specified 'predicate' with the specified // // integer 'value'. // // // ~Bind2ndInteger() = default; // // Destroy this object. // // // ACCESSORS // bool operator() (const int value) const; // // Return the result of calling the parameterized // // 'BINARY_PREDICATE' passing the specified 'value' as the first // // argument and the integer value passed on construction as the // // second argument. // }; //.. // Then, we implement the methods of the 'Bind2ndInteger' class: //.. // template <class BINARY_PREDICATE> // Bind2ndInteger<BINARY_PREDICATE>::Bind2ndInteger(int value, // const BINARY_PREDICATE& predicate) // : FunctorAdapter<BINARY_PREDICATE>::Type(predicate), d_bondValue(value) // { // } //.. // Here, we implement the 'operator()' member function that simply delegates to // 'BINARY_PREDICATE' //.. // template <class BINARY_PREDICATE> // bool Bind2ndInteger<BINARY_PREDICATE>::operator() (const int value) const // { // const BINARY_PREDICATE& predicate = *this; // return predicate(value, d_bondValue); // } //.. // Next, we define a function, 'intCompareFunction', that compares two // integers: //.. // bool intCompareFunction(const int lhs, const int rhs) // { // return lhs < rhs; // } //.. // Now, we define a 'Bind2ndInteger' object 'functorLessThan10' using the // 'std::less<int>' functor as the parameterized 'BINARY_PREDICATE' and invoke // the function call operator: //.. // Bind2ndInteger<std::less<int> > functorLessThan10(10, std::less<int>()); // // assert(functorLessThan10(1)); // assert(!functorLessThan10(12)); //.. // Finally, we define a 'Bind2ndInteger' object 'functionLessThan10' passing // the address of 'intCompareFunction' on construction and invoke the function // call operator: //.. // Bind2ndInteger<bool (*)(const int, const int)> // functionLessThan10(10, &intCompareFunction); // // assert(functionLessThan10(1)); // assert(!functionLessThan10(12)); //.. #include <bslscm_version.h> #include <bslmf_assert.h> #include <bslmf_functionpointertraits.h> #include <bsls_assert.h> namespace BloombergLP { namespace bslalg { // ==================================== // class FunctorAdapter_FunctionPointer // ==================================== template <class FUNCTION_POINTER> class FunctorAdapter_FunctionPointer { // This class provides a functor that delegates to the function referred to // by a function pointer supplied on construction. Delegation is supported // through the conversion operator, which implicitly returns a reference to // the parameterized 'FUNCTION_POINTER'. private: // DATA FUNCTION_POINTER d_function_p; // the pointer to the function public: // CREATORS explicit FunctorAdapter_FunctionPointer(FUNCTION_POINTER functionPtr); // Create a 'FunctorAdapter_FunctionPointer' object that will delegate // to the function referred to by the specified 'functionPtr'. // MANIPULATORS operator FUNCTION_POINTER& (); // Convert this object to the parameterized 'FUNCTION_POINTER' by // returning the function pointer supplied on construction. // ACCESSORS operator const FUNCTION_POINTER& () const; // Convert this object to the parameterized 'FUNCTION_POINTER' by // returning the function pointer supplied on construction. }; // ==================== // class FunctorAdapter // ==================== template <class CALLABLE_OBJECT> class FunctorAdapter { // This class provides a metafunction that defines an alias 'Type' for the // parameterized 'CALLABLE_OBJECT'. 'Type' is functor type that provides // the same operation as the parameterized 'CALLABLE_OBJECT'. Note that // function pointers are supported through a specialization of this // template. public: // PUBLIC TYPES typedef CALLABLE_OBJECT Type; // This 'typedef' is an alias for the functor. }; // ==================== // class FunctorAdapter // ==================== template <class FUNCTION> class FunctorAdapter<FUNCTION*> { // This specialization of 'FunctorAdapter' defines an alias 'Type' for a // functor that delegates to a function pointer matching the parameterized // 'FUNCTION' type. BSLMF_ASSERT(bslmf::IsFunctionPointer<FUNCTION*>::value); // This 'BSLMF_ASSERT' statement ensures that the parameter 'FUNCTION' // must be a function pointer. public: // PUBLIC TYPES typedef FunctorAdapter_FunctionPointer<FUNCTION*> Type; // This 'typedef' is an alias for a functor that delegates to the // function referred to by the function pointer matching the // parameterized 'FUNCTION' type. }; // ============================================================================ // TEMPLATE AND INLINE FUNCTION DEFINITIONS // ============================================================================ // ------------------------------------ // class FunctorAdapter_FunctionPointer // ------------------------------------ // CREATORS template <class FUNCTION_POINTER> inline FunctorAdapter_FunctionPointer<FUNCTION_POINTER> ::FunctorAdapter_FunctionPointer(FUNCTION_POINTER functionPtr) :d_function_p(functionPtr) { } // MANIPULATORS template <class FUNCTION_POINTER> inline FunctorAdapter_FunctionPointer<FUNCTION_POINTER> ::operator FUNCTION_POINTER& () { return d_function_p; } // ACCESSORS template <class FUNCTION_POINTER> inline FunctorAdapter_FunctionPointer<FUNCTION_POINTER> ::operator const FUNCTION_POINTER& () const { return d_function_p; } } // close package namespace } // 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 ----------------------------------