Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Dec 23, 2015, 7:16:33 PM (9 years ago)
Author:
muemart
Message:

Extend Functor to handle any callable objects (lambdas!). Had to modify (un)registerObject, because apparently you can't dynamic_cast lambdas. Also wanted to perfect forward the object from createFunctor until obj_, but MSVC didn't like that.
Including new and improved Functor tests.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/cpp11_v2/src/libraries/core/command/Functor.h

    r10876 r10975  
    118118#include <array>
    119119#include <typeindex>
     120#include <type_traits>
    120121#include <tuple>
    121122
     
    303304
    304305        protected:
    305             /// Casts the object and registers as destruction listener.
     306            /// Casts the object and registers as destruction listener if the object is a Destroyable.
     307            template<bool = std::is_base_of<Destroyable, O>::value>
    306308            inline void registerObject(O* object)
    307                 { Destroyable* base = dynamic_cast<Destroyable*>(object); if (base) { this->registerAsDestructionListener(base); } }
    308             /// Casts the object and unregisters as destruction listener.
     309                { this->registerAsDestructionListener(static_cast<Destroyable*>(object)); }
     310
     311            template<>
     312            inline void registerObject<false>(O* object) {}
     313
     314            /// Casts the object and unregisters as destruction listener if the object is a Destroyable.
     315            template<bool = std::is_base_of<Destroyable, O>::value>
    309316            inline void unregisterObject(O* object)
    310                 { Destroyable* base = dynamic_cast<Destroyable*>(object); if (base) { this->unregisterAsDestructionListener(base); } }
    311 
    312             /// Will be called by Destroyable::~Destroyable() if the stored object is deleted and the Functor is in safe mode.
     317                { this->unregisterAsDestructionListener(static_cast<Destroyable*>(object)); }
     318
     319            template<>
     320            inline void unregisterObject<false>(O* object) {}
     321
     322            /// Will be called by Destroyable::~Destroyable() if the stored object is a Destroyable and deleted and the Functor is in safe mode.
    313323            virtual inline void objectDeleted() override
    314324                { this->object_ = nullptr; }
     
    450460        @param O The class of the function
    451461        @param isconst True if the function is a const member-function
    452         @param P1 The type of the first parameter
    453         @param P2 The type of the second parameter
    454         @param P3 The type of the third parameter
    455         @param P4 The type of the fourth parameter
    456         @param P5 The type of the fifth parameter
     462        @param Params The types of the parameters
    457463
    458464        This template has many parameters and is usually not used directly. It is created by
     
    566572    };
    567573
     574
     575    /**
     576    @brief FunctorCallable is a child class of FunctorTemplate. It stores a callable
     577    object (e.g. a lambda or a class with operator()) inside and acts like any
     578    other functor. Note that it stores a \em copy of the object, not a reference or a pointer.
     579    Take care that this functor does not outlive objects that have been captured by reference
     580    in a lambda.
     581
     582    @param F The type of the callable object
     583    @param R The type of the return-value of the function
     584    @param isconst True if operator() is const
     585    @param Params The types of the parameters
     586
     587    This template can not be used directly when using lambdas - the type of a lambda
     588    is not specified. It can only really be used through the base-class Functor.
     589    */
     590    template <class F, class R, bool isconst, class... Params>
     591    class FunctorCallable : public FunctorTemplate<R, F, isconst, Params...>
     592    {
     593    public:
     594        FunctorCallable(const F& obj): FunctorTemplate<R, F, isconst, Params...>(&F::operator(), &obj_)
     595            , obj_(obj)
     596        {}
     597
     598    private:
     599        F obj_; ///< The callable object
     600    };
     601
     602    namespace detail
     603    {
     604        //Helper functions to deduce types and constness of operator() and return the correct FunctorCallable
     605        template <class F, class R, class... Params> inline FunctorMemberPtr<F> callableHelper(const F& obj, R(F::*func)(Params...) const) { return std::make_shared<FunctorCallable<F, R, true, Params...>>(obj); }
     606        template <class F, class R, class... Params> inline FunctorMemberPtr<F> callableHelper(const F& obj, R(F::*func)(Params...)) { return std::make_shared<FunctorCallable<F, R, false, Params...>>(obj); }
     607    }
     608
    568609    template <class R, class O, class OO, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...), OO* object) { return std::make_shared<FunctorTemplate<R, O, false, Params...>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
    569610    template <class R, class O, class OO, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...) const, OO* object) { return std::make_shared<FunctorTemplate<R, O, true, Params...>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
     
    573614
    574615    template <class R, class... Params> inline FunctorStaticPtr createFunctor(R (*functionPointer)(Params...)) { return std::make_shared<FunctorTemplate<R, void, false, Params...>>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
     616   
     617    template <class F> inline FunctorMemberPtr<F> createFunctor(const F& obj) { return detail::callableHelper(obj, &F::operator()); } ///< Creates a new Functor with a callable object
    575618}
    576619
Note: See TracChangeset for help on using the changeset viewer.