Deprecated: Function create_function() is deprecated in /home4/starstu4/public_html/cgi-bin/subhrajit.net/wiki/cookbook/geshi/geshi.php on line 4716

Warning: Cannot modify header information - headers already sent by (output started at /home4/starstu4/public_html/cgi-bin/subhrajit.net/wiki/cookbook/geshi/geshi.php:4716) in /home4/starstu4/public_html/cgi-bin/subhrajit.net/wiki/pmwiki.php on line 1319
Articles / C++ Explicit Functor - Personal Wiki of Subhrajit Bhattacharya
You are viewing this site in administrative mode. Click here to view in regular mode.
print Short URL for this page:[close]

Press Ctrl+C to copy
bookmark feedback/comment

Information Technology - Solutions and Ideas >>
C++ Explicit Functor
Jul 13, 2015


We define a c++11 class, ExplicitFunctor, which, behaving as a functor, can evaluate arbitrary members of any class. Consider the following use of the class:


#include <iostream>
#include <cstdlib>

#include "utils/misc_wrappers.h"

class addClass {
public:
    int addOneMember (int a) { return (a+1); }
};

class addFunctor {
public:
    int add_amount;
    addFunctor (int amount=1) : add_amount(amount) { }

    int operator() (int a) { return (a+add_amount); }
    int addTwoMember (int a) { return (a+2); }
};

int main(int argc, char *argv[])
{
    // Use with a non-functor class
    // ----------------------------

    // ExplicitFunctor that creates an instance of the 'addClass'
    ExplicitFunctor <addClass, int (addClass::*)(int)>  addone1;
    addone1.set_function_pointer (&addClass::addOneMember); // provide the member function to use

    ExplicitFunctor <addClass, int (addClass::*)(int)>  addone2 (NULL, &addClass::addOneMember);

    // User-provided instance of the 'addClass'
    addClass class_instance;

    ExplicitFunctor <addClass, int (addClass::*)(int)>  addone3 (&class_instance, &addClass::addOneMember);

    auto addone4 = CreateExplicitFunctor (&class_instance, &addClass::addOneMember);


    // Can be used with a functor class as well
    // ----------------------------------------

    // To use opeator()
    ExplicitFunctor <addFunctor, int (addFunctor::*)(int)>  addone5;

    // To use a member function
    ExplicitFunctor <addFunctor, int (addFunctor::*)(int)>  addtwo;
    addtwo.set_function_pointer (&addFunctor::addTwoMember);

    // User-provided instance of the 'addFunctor'
    addFunctor functor_instance(3);

    ExplicitFunctor <addFunctor, int (addFunctor::*)(int)>  addthree;
    addthree.set_functor_instance (&functor_instance);


    // Print
    // -----

    // All of these will print 6
    std::cout << addone1(5) << std::endl;
    std::cout << addone2(5) << std::endl;
    std::cout << addone3(5) << std::endl;
    std::cout << addone4(5) << std::endl;
    std::cout << addone5(5) << std::endl;
    // The following will print 7
    std::cout << addtwo(5) << std::endl;
    // The following will print 8
    std::cout << addthree(5) << std::endl;
}

 

The definition of ExplicitFunctor is as follows:

#ifndef __YAGSBPL_MISC_WRAPPERS_H
#define __YAGSBPL_MISC_WRAPPERS_H


// SFINAE for getting operator()
template <typename fun_ptr_type, fun_ptr_type fun_ptr> struct type_check;
template <typename functor_type, typename fun_ptr_type>
    fun_ptr_type  get_bracket_operator (type_check<fun_ptr_type, &functor_type::operator()>*)
        { return ( static_cast<fun_ptr_type>(&functor_type::operator()) ); }
template <typename functor_type, typename fun_ptr_type>
    fun_ptr_type  get_bracket_operator (...) { return (NULL); }

// --------------

template <class FunctorType, typename FunctionPointerType> // FunctionPointerType is a pointer type to a member function of F
class ExplicitFunctor {
    /* Declaration Syntax: ExplicitFunctor <functor_class, ... (functor_class::*)(...)>  ef;
       Use: ef (...)
    */

private:
    FunctorType* functor_instance_p;
    bool new_created;
    FunctionPointerType function_pointer;

public:

    // function_pointer instantiation: function_pointer = &F::f
    // ------------------------------------------

    ExplicitFunctor () : functor_instance_p(NULL), new_created(false), function_pointer(NULL) { /*init();*/ }
    ExplicitFunctor (FunctorType* in_pointer, FunctionPointerType in_func=NULL) :
                        functor_instance_p(NULL), new_created(false), function_pointer(NULL)  { set_pointers (in_pointer, in_func); }

    // check if empty
    bool empty (void) { return (functor_instance_p==NULL); }

    // ------------
    // explicit initializations

    void set_functor_instance (FunctorType* in_pointer=NULL) {
        if (in_pointer) {
            clear(); // clears current pointer
            functor_instance_p = in_pointer;
            new_created = false;
        }
        else if (!functor_instance_p) { // init() -- will initiate if already not initiated.
            functor_instance_p = new FunctorType;
            new_created = true;
        }
    }

    void set_function_pointer (FunctionPointerType in_func=NULL) {
        if (in_func)
            function_pointer = in_func;
        else
            function_pointer = get_bracket_operator<FunctorType,FunctionPointerType>(0);
    }

    void set_pointers (FunctorType* in_pointer=NULL, FunctionPointerType in_func=NULL) {
        set_functor_instance (in_pointer);
        set_function_pointer (in_func);
    }

    // ------------
    // operator()

    template <class F>
    struct return_type;

    template <class R, class... A>
    struct return_type <R (FunctorType::*)(A...)> {
      typedef R type;
    };

    // forwarded
    template <class... A>
    typename return_type<FunctionPointerType>::type  operator() (A && ... args) { // receive everything by reference
        if (!functor_instance_p) set_functor_instance();
        if (!function_pointer)  set_function_pointer();
        return ( (functor_instance_p->*function_pointer) (std::forward<A>(args)...) );
    }

    // ------------

    // Delete / destructor

    void clear (void) {
        if (new_created)
            delete functor_instance_p;
        functor_instance_p = NULL;
        new_created = false;
    }

    ~ExplicitFunctor () {
        clear();
    }
};

// ----------------------

template <class FunctorType, typename FunctionPointerType>
ExplicitFunctor<FunctorType,FunctionPointerType>
    CreateExplicitFunctor (FunctorType* functor_instance_p, FunctionPointerType function_pointer)
        { return (ExplicitFunctor<FunctorType,FunctionPointerType> (functor_instance_p, function_pointer)); }

#endif

Cpp IT Programming Library

Page last modified on July 13, 2015, at 03:46 PM EST.
(cc) Subhrajit Bhattacharya