// bdlf_memfn.h -*-C++-*- // ---------------------------------------------------------------------------- // NOTICE // // This component is not up to date with current BDE coding standards, and // should not be used as an example for new development. // ---------------------------------------------------------------------------- #ifndef INCLUDED_BDLF_MEMFN #define INCLUDED_BDLF_MEMFN #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide member function pointer wrapper classes and utility. // //@CLASSES: // bdlf::MemFn: member function wrapper // bdlf::MemFnInstance: member function wrapper with embedded instance pointer // bdlf::MemFnUtil: utility for constructing wrapper objects // //@SEE_ALSO: bdlf_bind // //@DESCRIPTION: This component provides a member function pointer wrapper that // wraps a member function pointer such that it can be invoked in syntactically // the same manner as a free function. Two wrappers, each supporting member // function pointers that accept from zero to fourteen arguments, are provided, // as well as a utility to create such wrappers. Member function wrappers are // commonly used as function objects for standard algorithms. // // The first wrapper, 'bdlf::MemFn', contains a member function pointer and // must be invoked with the first argument being a pointer or reference to the // instance on which the function should be invoked, with the remaining // arguments passed as arguments to the member function; that is, a wrapper // 'memFn' containing a pointer to a given 'memberFunction' can be invoked as // 'memFn(&object, args...)' as opposed to 'object.memberFunction(args...)'. // // The second wrapper, 'bdlf::MemFnInstance', contains both the member function // pointer and a pointer to an instance of the type which contains the member, // and is invoked with arguments which are passed as arguments to the member // function; that is, a wrapper 'memFnInstance' containing pointers to both a // given 'memberFunction' and to an 'object' instance can be invoked as // 'memFnInstance(args...)' as opposed to 'object.memberFunction(args...)'. // // Finally, the 'bdlf::MemFnUtil' utility class provides utility functions for // constructing 'bdlf::MemFn' and 'bdlf::MemFnInstance' objects. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Basic Usage /// - - - - - - - - - - - // To illustrate basic usage more concretely, let us introduce a generic type: //.. // class MyObject { // public: // void doSomething(int, const char *); // }; //.. // The following function invokes the member function 'doSomething' on the // specified 'objectPtr', with the two arguments 100 and "Hello", in two // different ways. In both cases, 'object' is passed as parameter to a // function, and a wrapper is built containing a pointer to the 'doSomething' // member function. In the 'bdlf::MemFn' case, the wrapper can be built once, // so we make it a 'static' local variable: //.. // void doSomethingWithMemFn(MyObject *objectPtr) // { // typedef bdlf::MemFn<void (MyObject::*)(int, const char *)> MemFnType; // static MemFnType func(&MyObject::doSomething); // // func(objectPtr, 100, "Hello"); // } //.. // In the 'bdlf::MemFnInstance' case, the wrapper needs to contain the object // as well, so it must be created at every function call: //.. // void doSomethingWithMemFnInstance(MyObject *objectPtr) // { // typedef bdlf::MemFnInstance<void (MyObject::*)(int, const char*), // MyObject*> MemFnInstanceType; // MemFnInstanceType func(&MyObject::doSomething, objectPtr); // func(100, "Hello"); // } //.. // This latter example is for exposition only. It would be much easier to // invoke the member function directly. Note that both function calls // ultimately result in the member function call: //.. // objectPtr->doSomething(100, "Hello"); //.. // ///Example 2: Usage with Standard Algorithms ///- - - - - - - - - - - - - - - - - - - - - // The following example demonstrates the use of 'bdlf::MemFn' with the // standard algorithms 'find_if' and 'for_each'. First we declare the // 'MyConnection' and 'MyConnectionManager' classes used in the example, // keeping the class definitions short to highlight the member functions for // which we will later build wrappers: //.. // class MyConnection { // // // DATA (not shown) // // public: // // CREATORS (not shown) // // // MANIPULATORS // void disconnect(); // // // ACCESSORS // bool isAvailable() const; // }; // // class MyConnectionManager { // // // PRIVATE TYPES // typedef bsl::list<MyConnection *> MyConnectionList; // // // DATA // MyConnectionList d_list; // // public: // // CREATORS (not shown) // // // MANIPULATORS // void disconnectAll(); // // // ACCESSORS // MyConnection *nextAvailable() const; // }; //.. // The 'nextAvailable' function returns the next 'MyConnection' object that is // available. The 'find_if' algorithm is used to search the list for the first // 'MyConnection' object that is available. 'find_if' invokes the provided // function object for each item in the list until a 'true' result is returned, // or the end of the list is reached. A 'bdlf::MemFn' object bound to the // 'MyConnection::isAvailable' member function is used as the test functor. // Note that the type of this object is never spelled out, it is built on the // fly using the 'bdlf::MemFnUtil' utility before being passed as a functor to // the 'bsl::find_if' algorithm: //.. // MyConnection *MyConnectionManager::nextAvailable() const // { // MyConnectionList::const_iterator it = // bsl::find_if(d_list.begin(), // d_list.end(), // bdlf::MemFnUtil::memFn(&MyConnection::isAvailable)); // return it == d_list.end() ? 0 : *it; // } //.. // The 'disconnectAll' function calls 'disconnect' on each 'MyConnection' // object in the list. The 'for_each' algorithm is used to iterate through // each 'MyConnection' object in the list and invoke the 'disconnect' method: //.. // void MyConnectionManager::disconnectAll() // { // bsl::for_each(d_list.begin(), // d_list.end(), // bdlf::MemFnUtil::memFn(&MyConnection::disconnect)); // } //.. #include <bdlscm_version.h> #include <bslalg_constructorproxy.h> #include <bslma_default.h> #include <bslma_usesbslmaallocator.h> #include <bslmf_assert.h> #include <bslmf_forwardingtype.h> #include <bslmf_haspointersemantics.h> #include <bslmf_integralconstant.h> #include <bslmf_ispointer.h> #include <bslmf_memberfunctionpointertraits.h> #include <bslmf_typelist.h> #include <bslma_allocator.h> namespace BloombergLP { namespace bdlf { // ======================= // class MemFn_Dereference // ======================= template <class OBJTYPE> struct MemFn_Dereference { // This utility is used to convert user supplied values to references to // 'OBJTYPE' for object references that are directly convertible to // 'OBJTYPE', the reference is returned directly. For pointers and objects // that are not directly convertible (e.g., "smart pointers to 'OBJTYPE'"), // the result of '*OBJECT' is returned, where 'OBJECT' is the pointer or // object reference. static inline OBJTYPE& derefImp(OBJTYPE& obj, bsl::false_type *) { return obj; } template <class TYPE> static inline OBJTYPE& derefImp(TYPE& obj, bsl::true_type *) { return *obj; } template <class TYPE> static inline OBJTYPE& derefImp(const TYPE& obj, bsl::true_type *) { return *obj; } template <class TYPE> static inline OBJTYPE& deref(TYPE& obj) { return derefImp(obj, (bslmf::HasPointerSemantics<TYPE> *)0); } template <class TYPE> static inline OBJTYPE& deref(const TYPE& obj) { return derefImp(obj, (bslmf::HasPointerSemantics<TYPE> *)0); } }; // =========== // class MemFn // =========== template <class PROTOTYPE> class MemFn { // This class encapsulates a member function pointer having the // parameterized 'PROTOTYPE', such that the member function pointer can be // invoked in syntactically the same manner as a free function pointer. // When invoking a member function through this wrapper, the first argument // must be a pointer or reference to the instance on which to invoke the // member function pointer. Zero to fourteen additional arguments may be // specified depending on 'PROTOTYPE'. // PRIVATE TYPES typedef bslmf::MemberFunctionPointerTraits<PROTOTYPE> Traits; // ASSERTIONS BSLMF_ASSERT(Traits::IS_MEMBER_FUNCTION_PTR); // otherwise none of the // 'typedef's below make any // sense public: // TYPES typedef typename Traits::ResultType ResultType; // 'ResultType' is an alias for the type of the object returned by an // invocation of this member function wrapper. typedef typename Traits::ArgumentList Args; // 'Args' is an alias for the list of arguments passed to an invocation // of this member function wrapper, expressed as a 'bslmf_Typelist'. typedef typename Traits::ClassType ObjectType; // 'ObjectType' is an alias for the class type to which the member // function that is wrapped belongs. typedef PROTOTYPE Prototype; // 'ProtoType' is an alias for the parameterized 'PROTOTYPE' passed as // a template argument to this wrapper. typedef PROTOTYPE ProtoType; // 'ProtoType' is an alias for the parameterized 'PROTOTYPE' passed as // a template argument to this wrapper. // // *DEPRECATED*: Use 'Prototype' instead. private: // PRIVATE TYPES typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 1, Args>::TypeOrDefault>::Type ARG1; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 2, Args>::TypeOrDefault>::Type ARG2; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 3, Args>::TypeOrDefault>::Type ARG3; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 4, Args>::TypeOrDefault>::Type ARG4; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 5, Args>::TypeOrDefault>::Type ARG5; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 6, Args>::TypeOrDefault>::Type ARG6; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 7, Args>::TypeOrDefault>::Type ARG7; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 8, Args>::TypeOrDefault>::Type ARG8; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 9, Args>::TypeOrDefault>::Type ARG9; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf<10, Args>::TypeOrDefault>::Type ARG10; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf<11, Args>::TypeOrDefault>::Type ARG11; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf<12, Args>::TypeOrDefault>::Type ARG12; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf<13, Args>::TypeOrDefault>::Type ARG13; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf<14, Args>::TypeOrDefault>::Type ARG14; // 'AN', for 'N' from 1 up to 14, is an alias for the type of the 'N'th // argument in the 'Args' list. typedef MemFn_Dereference<ObjectType> Deref; // DATA PROTOTYPE d_func_p; // pointer to member function public: // CREATORS explicit MemFn(PROTOTYPE func); // Create a member function pointer wrapper holding the address of the // specified 'func' member function having the parameterized // 'PROTOTYPE'. MemFn(const MemFn<PROTOTYPE>& original); // Create a member function pointer wrapper holding the address of the // same member function as the specified 'original' object. // ~MemFn(); // Destroy this object. Note that this trivial destructor is generated // by the compiler. // ACCESSORS template <class INSTANCE> ResultType operator()(INSTANCE& object) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with no specified arguments, and // return the result of this invocation, or 'void' if this member // function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1', // and return the result of this invocation, or 'void' if this member // function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1); // see NOTES above } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg2', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2); // etc. } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg3', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg4', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg5', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg6', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg7', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg8', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg9', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg10', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg11', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg12', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12, ARG13 arg13) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg13', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); } template <class INSTANCE> ResultType operator()(INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12, ARG13 arg13, ARG14 arg14) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1' up // to 'arg14', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); } template <class INSTANCE> ResultType operator()(const INSTANCE& object) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with no arguments, and return the // result of this invocation, or 'void' if this member function pointer // does not return a result. { return (Deref::deref(object).*d_func_p)(); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified argument 'arg1', // and return the result of this invocation, or 'void' if this member // function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg2', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg3', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg4', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg5', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg6', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg7', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg8', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg9', and return the result of this invocation, or 'void' if // this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg10', and return the result of this invocation, or 'void' // if this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg11', and return the result of this invocation, or 'void' // if this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg12', and return the result of this invocation, or 'void' // if this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12, ARG13 arg13) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg13', and return the result of this invocation, or 'void' // if this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); } template <class INSTANCE> ResultType operator()(const INSTANCE& object, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12, ARG13 arg13, ARG14 arg14) const // Invoke the member function pointer held by this wrapper on the // specified 'object' reference to a non-modifiable instance of the // parameterized 'INSTANCE' type, with the specified arguments 'arg1' // up to 'arg14', and return the result of this invocation, or 'void' // if this member function pointer does not return a result. { return (Deref::deref(object).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); } }; // =================== // class MemFnInstance // =================== template <class PROTOTYPE, class INSTANCE> class MemFnInstance { // This class encapsulates a member function pointer having the // parameterized 'PROTOTYPE' and a value of the parameterized 'INSTANCE' // type, which can be either be the type of object referred to by the // 'PROTOTYPE', or a pointer to one, such that the member function pointer // can be invoked on the wrapped instance in syntactically the same manner // as a free function pointer. Zero to fourteen additional arguments may // be specified depending on the 'PROTOTYPE'. Note that whether 'INSTANCE' // is a pointer or an object is determined by whether it has pointer // semantics or not (as determined by the 'bslmf::HasPointerSemantics' type // trait). Also note that if 'INSTANCE' is an object that does not have // pointer semantics, 'PROTOTYPE' must be const-qualified. // PRIVATE TYPES typedef bslmf::MemberFunctionPointerTraits<PROTOTYPE> Traits; public: // TYPES typedef typename Traits::ResultType ResultType; // 'ResultType' is an alias for the type of the object returned by an // invocation of this member function wrapper. typedef typename Traits::ArgumentList Args; // 'Args' is an alias for the list of arguments passed to an invocation // of this member function wrapper, expressed as a 'bslmf_Typelist'. typedef typename Traits::ClassType ObjectType; // 'ObjectType' is an alias for the class type to which the member // function that is wrapped belongs. typedef PROTOTYPE Prototype; // 'ProtoType' is an alias for the parameterized 'PROTOTYPE' passed as // a template argument to this wrapper. typedef PROTOTYPE ProtoType; // 'ProtoType' is an alias for the parameterized 'PROTOTYPE' passed as // a template argument to this wrapper. // // *DEPRECATED*: Use 'Prototype' instead. typedef MemFn_Dereference<ObjectType> Deref; private: // PRIVATE TYPES typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 1, Args>::TypeOrDefault>::Type ARG1; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 2, Args>::TypeOrDefault>::Type ARG2; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 3, Args>::TypeOrDefault>::Type ARG3; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 4, Args>::TypeOrDefault>::Type ARG4; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 5, Args>::TypeOrDefault>::Type ARG5; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 6, Args>::TypeOrDefault>::Type ARG6; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 7, Args>::TypeOrDefault>::Type ARG7; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 8, Args>::TypeOrDefault>::Type ARG8; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf< 9, Args>::TypeOrDefault>::Type ARG9; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf<10, Args>::TypeOrDefault>::Type ARG10; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf<11, Args>::TypeOrDefault>::Type ARG11; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf<12, Args>::TypeOrDefault>::Type ARG12; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf<13, Args>::TypeOrDefault>::Type ARG13; typedef typename bslmf::ForwardingType< typename bslmf::TypeListTypeOf<14, Args>::TypeOrDefault>::Type ARG14; // 'AN', for 'N' from 1 up to 14, is an alias for the type of the 'N'th // argument in the 'Args' list. // DATA PROTOTYPE d_func_p; // pointer to member function bslalg::ConstructorProxy<INSTANCE> d_obj; // object instance, or // pointer to such // PRIVATE ACCESSORS public: // CREATORS MemFnInstance(PROTOTYPE func, const INSTANCE& object, bslma::Allocator *basicAllocator = 0); // Create a member function pointer wrapper around the specified 'func' // member function pointer of the parameterized 'PROTOTYPE', that is // invocable on the specified 'object' instance of the parameterized // 'INSTANCE'. Optionally specify a 'basicAllocator' used to supply // memory. If 'basicAllocator' is 0, the currently installed default // allocator is used. MemFnInstance(const MemFnInstance& original, bslma::Allocator *basicAllocator = 0); // Create a member function pointer wrapper around the same member // function and instance pointed to by the specified 'original' object. // Optionally specify a 'basicAllocator' used to supply memory. If // 'basicAllocator' is 0, the currently installed default allocator is // used. ~MemFnInstance(); // Destroy this object. // MANIPULATORS MemFnInstance& operator=(const MemFnInstance& rhs); // Assign to this member function pointer wrapper the same member // function and instance pointed to by the specified 'rhs' member // function pointer wrapper, and return a reference to this modifiable // member function pointer wrapper. // ACCESSORS ResultType operator()() const; ResultType operator()(ARG1 arg1) const; ResultType operator()(ARG1 arg1, ARG2 arg2) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12, ARG13 arg13) const; ResultType operator()(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12, ARG13 arg13, ARG14 arg14) const; // Invoke the member function pointer held by this wrapper on the // provided object with the specified 'arg1' up to 'argN' as arguments, // with 'N' being the number of arguments of the member function, and // return the result of this invocation, or 'void' if this member // function pointer does not return a result. }; // ================ // struct MemFnUtil // ================ struct MemFnUtil { // The methods provided in this utility are used for constructing 'MemFn' // and 'MemFnInstance' objects from function pointers. // CLASS METHODS template <class PROTOTYPE> static MemFn<PROTOTYPE> memFn(PROTOTYPE func); // Return a 'MemFn' member function wrapper that encapsulates the // specified 'func' member function pointer of the parameterized // 'PROTOTYPE'. template <class PROTOTYPE, class INSTANCE> static MemFnInstance<PROTOTYPE, INSTANCE> memFn(PROTOTYPE func, const INSTANCE& object); // Return a 'MemFnInstance' member function wrapper that encapsulates // the specified 'func' member function pointer of the parameterized // 'PROTOTYPE' and the specified 'object' instance of the parameterized // 'INSTANCE' type. }; // ============================================================================ // INLINE FUNCTION DEFINITIONS // ============================================================================ // ----------- // class MemFn // ----------- // CREATORS template <class PROTOTYPE> inline MemFn<PROTOTYPE>::MemFn(PROTOTYPE func) : d_func_p(func) { } template <class PROTOTYPE> inline MemFn<PROTOTYPE>::MemFn(const MemFn<PROTOTYPE>& original) : d_func_p(original.d_func_p) { } // ------------------- // class MemFnInstance // ------------------- // CREATORS template <class PROTOTYPE, class INSTANCE> inline MemFnInstance<PROTOTYPE, INSTANCE>::MemFnInstance( const MemFnInstance<PROTOTYPE, INSTANCE>& original, bslma::Allocator *basicAllocator) : d_func_p(original.d_func_p) , d_obj(original.d_obj, bslma::Default::allocator(basicAllocator)) { } template <class PROTOTYPE, class INSTANCE> inline MemFnInstance<PROTOTYPE, INSTANCE>::MemFnInstance( PROTOTYPE func, const INSTANCE& object, bslma::Allocator *basicAllocator) : d_func_p(func) , d_obj(object, bslma::Default::allocator(basicAllocator)) { } template <class PROTOTYPE, class INSTANCE> inline MemFnInstance<PROTOTYPE, INSTANCE>::~MemFnInstance() { } // MANIPULATORS template <class PROTOTYPE, class INSTANCE> inline MemFnInstance<PROTOTYPE, INSTANCE>& MemFnInstance<PROTOTYPE, INSTANCE>::operator=( const MemFnInstance& rhs) { d_func_p = rhs.d_func_p; d_obj.object() = rhs.d_obj.object(); return *this; } // ACCESSORS template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()() const { return (Deref::deref(d_obj.object()).*d_func_p)(); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()(ARG1 arg1) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()(ARG1 arg1, ARG2 arg2) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4, arg5); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12, ARG13 arg13) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); } template <class PROTOTYPE, class INSTANCE> inline typename MemFnInstance<PROTOTYPE, INSTANCE>::ResultType MemFnInstance<PROTOTYPE, INSTANCE>::operator()( ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9, ARG10 arg10, ARG11 arg11, ARG12 arg12, ARG13 arg13, ARG14 arg14) const { return (Deref::deref(d_obj.object()).*d_func_p)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); } // ---------------- // struct MemFnUtil // ---------------- // CLASS METHODS template <class PROTOTYPE> inline MemFn<PROTOTYPE> MemFnUtil::memFn(PROTOTYPE func) { return MemFn<PROTOTYPE>(func); } template <class PROTOTYPE, class INSTANCE> inline MemFnInstance<PROTOTYPE, INSTANCE> MemFnUtil::memFn(PROTOTYPE func, const INSTANCE& object) { return MemFnInstance<PROTOTYPE, INSTANCE>(func, object); } } // close package namespace } // close enterprise namespace // ============================================================================ // TYPE TRAITS // ============================================================================ namespace BloombergLP { namespace bslma { template <class PROTOTYPE, class INSTANCE> struct UsesBslmaAllocator<bdlf::MemFnInstance<PROTOTYPE, INSTANCE> > : bsl::true_type {}; } // close namespace bslma namespace bslmf { template <class PROTOTYPE, class INSTANCE> struct IsBitwiseMoveable<bdlf::MemFnInstance<PROTOTYPE, INSTANCE> > : IsBitwiseMoveable<INSTANCE> {}; template <class PROTOTYPE> struct IsBitwiseMoveable<bdlf::MemFn<PROTOTYPE> > : bsl::true_type { // This bitwise moveable trait is redundant as it is already implied by the // 'is_trivially_copyable' trait below. We retain this definition, // however, as it can potentially save a level of template instantiation. }; } // close namespace bslmf } // close enterprise namespace namespace bsl { template <class PROTOTYPE> struct is_trivially_copyable<BloombergLP::bdlf::MemFn<PROTOTYPE> > : bsl::true_type {}; } // close namespace bsl #endif // ---------------------------------------------------------------------------- // Copyright 2015 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 ----------------------------------