Program Listing for File function_objects.hpp

Return to documentation for file (include/ecl/utilities/function_objects.hpp)

/*****************************************************************************
** Ifdefs
*****************************************************************************/

#ifndef ECL_UTILITIES_FUNCTION_OBJECTS_HPP_
#define ECL_UTILITIES_FUNCTION_OBJECTS_HPP_

/*****************************************************************************
** Includes
*****************************************************************************/

#include <ecl/concepts/nullary_function.hpp>
#include "../utilities/references.hpp"

/*****************************************************************************
** Namespaces
*****************************************************************************/

namespace ecl {

/*****************************************************************************
** Using
*****************************************************************************/

/*****************************************************************************
** Interface [NullaryFunction]
*****************************************************************************/
template <typename R = void>
class NullaryFunction {
public:
    typedef R result_type;
    virtual result_type operator()() = 0;
    virtual ~NullaryFunction() {};
};

/*****************************************************************************
** Interface [UnaryFunction]
*****************************************************************************/

template <typename A, typename R = void>
class UnaryFunction {
public:
    typedef R result_type;
    typedef A argument_type;
    virtual result_type operator()(argument_type arg) = 0;
    virtual ~UnaryFunction() {};
};

/*****************************************************************************
** Interface [BinaryFunction]
*****************************************************************************/
template <typename A1, typename A2, typename R = void>
class BinaryFunction {
public:
    typedef R result_type;
    typedef A1 first_argument_type;
    typedef A2 second_argument_type;
    virtual result_type operator()(first_argument_type arg1, second_argument_type arg2) = 0;
    virtual ~BinaryFunction() {};
};

/*****************************************************************************
** Interface [FreeFunctions]
*****************************************************************************/
template <typename R = void>
class NullaryFreeFunction : public NullaryFunction<R>
{
public:
    NullaryFreeFunction( R (*function)() ) : free_function(function) {}
    virtual ~NullaryFreeFunction() {};
    R operator()() { return free_function(); }

private:
    R (*free_function)();
};

template <>
class NullaryFreeFunction<void> : public NullaryFunction<void>
{
public:
    NullaryFreeFunction( void (*function)() ) : free_function(function) {}

    virtual ~NullaryFreeFunction() {};
    void operator()() { free_function(); }

private:
    void (*free_function)();
};

template <typename A, typename R = void>
class UnaryFreeFunction : public UnaryFunction<A,R>
{
public:
    UnaryFreeFunction( R (*function)(A) ) : free_function(function) {}

    virtual ~UnaryFreeFunction() {};
    R operator()(A a) { return free_function(a); }

private:
    R (*free_function)(A);
};

template <typename A>
class UnaryFreeFunction<A,void> : public UnaryFunction<A,void>
{
public:
    UnaryFreeFunction( void (*function)(A) ) : free_function(function) {}

    virtual ~UnaryFreeFunction() {};
    void operator()(A a) { free_function(a); }

private:
    void (*free_function)(A);
};

/*****************************************************************************
** Interface [BoundFreeFunctions]
*****************************************************************************/
template <typename A, typename R = void>
class BoundUnaryFreeFunction : public NullaryFunction<R>
{
public:
    BoundUnaryFreeFunction( R (*function)(A), A a ) : free_function(function), argument(a) {}
    virtual ~BoundUnaryFreeFunction() {};
    R operator()() { return free_function(argument); }

private:
    R (*free_function)(A);
    A argument;
};

template <typename A>
class BoundUnaryFreeFunction<A,void> : public NullaryFunction<void>
{
public:
    BoundUnaryFreeFunction( void (*function)(A), A a ) : free_function(function), argument(a) {}
    virtual ~BoundUnaryFreeFunction() {};
    void operator()() { free_function(argument); }

private:
    void (*free_function)(A);
    A argument;
};

/*****************************************************************************
 * Interface [MemberFunctions]
 *****************************************************************************
 * Could make copies+refs here, just like mem_fun and mem_fun_ref but I can't
 * see the need for copy style setups.
 ****************************************************************************/

template <typename C, typename R = void>
class NullaryMemberFunction  : public UnaryFunction<C&,R> {
public:
    NullaryMemberFunction( R (C::*function)()) : member_function(function) {}
    virtual ~NullaryMemberFunction() {};
    R operator()(C &class_object) {
        return (class_object.*member_function)();
    }
private:
    R (C::*member_function)();
};

template <typename C>
class NullaryMemberFunction<C,void>  : public UnaryFunction<C&,void> {
public:
    NullaryMemberFunction( void (C::*function)()) : member_function(function) {}
    virtual ~NullaryMemberFunction() {};
    void operator()(C &class_object) {
        (class_object.*member_function)();
    }
private:
    void (C::*member_function)();
};

template <typename C, typename A, typename R = void>
class UnaryMemberFunction  : public BinaryFunction<C&,A,R> {
public:
    UnaryMemberFunction( R (C::*function)(A)) : member_function(function) {}
    virtual ~UnaryMemberFunction() {};
    R operator()(C &class_object, A a) {
        return (class_object.*member_function)(a);
    }
private:
    R (C::*member_function)(A);
};

template <typename C, typename A>
class UnaryMemberFunction<C,A,void>  : public BinaryFunction<C&,A,void> {
public:
    UnaryMemberFunction( void (C::*function)(A)) : member_function(function) {}
    virtual ~UnaryMemberFunction() {};
    void operator()(C &class_object, A a) {
        (class_object.*member_function)(a);
    }
private:
    void (C::*member_function)(A);
};

/*****************************************************************************
** Interface [BoundMemberFunctions]
*****************************************************************************/

template <typename C, typename R = void>
class BoundNullaryMemberFunction : public NullaryFunction<R> {
public:
    BoundNullaryMemberFunction( R (C::*function)(), C &class_object) :
        member_class(class_object),
        member_function(function)
    {}
    virtual ~BoundNullaryMemberFunction() {};
    R operator()() { return (member_class.*member_function)(); }

private:
    C &member_class;
    R (C::*member_function)();
};

template <typename C>
class BoundNullaryMemberFunction<C,void> : public NullaryFunction<void> {
public:
    BoundNullaryMemberFunction( void (C::*function)(), C &class_object) :
        member_class(class_object),
        member_function(function)
    {}

    virtual ~BoundNullaryMemberFunction() {};
    void operator()() { (member_class.*member_function)(); }

private:
    C &member_class;
    void (C::*member_function)();
};

template <typename C, typename A, typename R = void>
class PartiallyBoundUnaryMemberFunction : public UnaryFunction<A,R> {
public:
    PartiallyBoundUnaryMemberFunction( R (C::*function)(A), C &class_object) :
        member_class(class_object),
        member_function(function)
    {}
    virtual ~PartiallyBoundUnaryMemberFunction() {};
    R operator()(A a) {
        return (member_class.*member_function)(a);
    }
private:
    C &member_class;
    void (C::*member_function)(A);
};
template <typename C, typename A, typename R = void>
class BoundUnaryMemberFunction : public NullaryFunction<R> {
public:
    BoundUnaryMemberFunction( R (C::*function)(A), C &class_object, A a) :
        member_class(class_object),
        member_function(function),
        argument(a)
    {}
    virtual ~BoundUnaryMemberFunction() {};
    R operator()() {
        return (member_class.*member_function)(argument);
    }
private:
    C &member_class;
    void (C::*member_function)(A);
    A argument;
};

template <typename C, typename A, typename B, typename R = void>
class PartiallyBoundBinaryMemberFunction : public BinaryFunction<A,B,R> {
public:
        PartiallyBoundBinaryMemberFunction( R (C::*function)(A, B), C &class_object) :
                member_class(class_object),
                member_function(function)
        {}
        virtual ~PartiallyBoundBinaryMemberFunction() {};
        R operator()(A a, B b) {
                return (member_class.*member_function)(a, b);
        }
private:
        C &member_class;
        void (C::*member_function)(A, B);
};
/*****************************************************************************
** Function Object Wrappers
*****************************************************************************/
template <typename FunctionObject, typename Result = void>
class NullaryFunctionCopy : public NullaryFunction<Result>
{
public:
    NullaryFunctionCopy(const FunctionObject &f_o ) : function_object(f_o) {
        ecl_compile_time_concept_check(NullaryFunction<FunctionObject>);
    }
    virtual ~NullaryFunctionCopy() {};
    Result operator()() { return function_object(); }

private:
    FunctionObject function_object;
};

template <typename FunctionObject>
class NullaryFunctionCopy<FunctionObject,void> : public NullaryFunction<void>
{
public:
    explicit NullaryFunctionCopy( const FunctionObject &f_o ) : function_object(f_o) {
        ecl_compile_time_concept_check(NullaryFunction<FunctionObject>);
    }
    virtual ~NullaryFunctionCopy() {};
    void operator()() { function_object(); }

private:
    FunctionObject function_object;
};

template <typename FunctionObject, typename Result = void>
class NullaryFunctionReference : public NullaryFunction<Result>
{
public:
    explicit NullaryFunctionReference( const ReferenceWrapper<FunctionObject> &wrapper ) : function_object(wrapper.reference()) {
        ecl_compile_time_concept_check(NullaryFunction<FunctionObject>);
    }
    virtual ~NullaryFunctionReference() {};
    Result operator()() { return function_object(); }

private:
    FunctionObject &function_object;
};

template <typename FunctionObject>
class NullaryFunctionReference< FunctionObject, void > : public NullaryFunction<void>
{
public:
    explicit NullaryFunctionReference( const ReferenceWrapper<FunctionObject> &wrapper ) : function_object(wrapper.reference()) {
        ecl_compile_time_concept_check(NullaryFunction<FunctionObject>);
    }
    virtual ~NullaryFunctionReference() {};
    void operator()() { function_object(); }

private:
    FunctionObject &function_object;
};

template <typename FunctionObject, typename T, typename Result = void>
class UnaryFunctionCopy : public UnaryFunction<T, Result>
{
public:
    UnaryFunctionCopy(const FunctionObject &f_o ) : function_object(f_o) {
//      ecl_compile_time_concept_check(UnaryFunction<FunctionObject>);
    }
    virtual ~UnaryFunctionCopy() {};
    Result operator()(T t) { return function_object(t); }

private:
    FunctionObject function_object;
};

template <typename FunctionObject, typename T>
class UnaryFunctionCopy<FunctionObject,T,void> : public UnaryFunction<T, void>
{
public:
    explicit UnaryFunctionCopy( const FunctionObject &f_o ) : function_object(f_o) {
//      ecl_compile_time_concept_check(UnaryFunction<FunctionObject>);
    }
    virtual ~UnaryFunctionCopy() {};
    void operator()(T t) { function_object(t); }

private:
    FunctionObject function_object;
};

template <typename FunctionObject, typename T, typename Result = void>
class UnaryFunctionReference : public UnaryFunction<T, Result>
{
public:
    explicit UnaryFunctionReference( const ReferenceWrapper<FunctionObject> &wrapper ) : function_object(wrapper.reference()) {
//      ecl_compile_time_concept_check(UnaryFunction<FunctionObject>);
    }

    virtual ~UnaryFunctionReference() {};
    Result operator()(T t) { return function_object(t); }

private:
    FunctionObject &function_object;
};

template <typename ReferenceWrapper, typename T>
class UnaryFunctionReference< ReferenceWrapper, T, void > : public UnaryFunction<T,void>
{
public:
    typedef typename ReferenceWrapper::type FunctionObject;
    explicit UnaryFunctionReference( const ReferenceWrapper &wrapper ) : function_object(wrapper.reference()) {
//      ecl_compile_time_concept_check(UnaryFunction<FunctionObject>);
    }
    virtual ~UnaryFunctionReference() {};
    void operator()(T t) { function_object(t); }

private:
    FunctionObject &function_object;
};

/*****************************************************************************
** Nullary Function Generators
*****************************************************************************/

template <typename R>
NullaryFreeFunction<R> generateFunctionObject( R (*function)() ) {
    return NullaryFreeFunction<R>( function );
}

template <typename A, typename R>
UnaryFreeFunction<A,R> generateFunctionObject( R (*function)(A) ) {
    return UnaryFreeFunction<A,R>( function );
}

template <typename A, typename R, typename I>
BoundUnaryFreeFunction<A,R> generateFunctionObject( R (*function)(A), I& a ) {
    return BoundUnaryFreeFunction<A,R>( function, a );
}

template <typename A, typename R, typename I>
BoundUnaryFreeFunction<A,R> generateFunctionObject( R (*function)(A), const I& a ) {
    return BoundUnaryFreeFunction<A,R>( function, a );
}

template <typename C, typename R>
NullaryMemberFunction<C,R> generateFunctionObject( R (C::*function)() ) {
    return NullaryMemberFunction<C,R>( function );
}

template <typename C, typename R>
BoundNullaryMemberFunction<C,R> generateFunctionObject( R (C::*function)(), C &c ) {
    return BoundNullaryMemberFunction<C,R>( function, c );
}

template <typename C, typename A, typename R>
UnaryMemberFunction<C,A,R> generateFunctionObject( R (C::*function)(A) ) {
    return UnaryMemberFunction<C,A,R>( function );
}

template <typename C, typename A, typename R>
PartiallyBoundUnaryMemberFunction<C,A,R> generateFunctionObject( R (C::*function)(A), C& c) {
    return PartiallyBoundUnaryMemberFunction<C,A,R>( function, c);
}

template <typename C, typename A, typename R, typename I>
BoundUnaryMemberFunction<C,A,R> generateFunctionObject( R (C::*function)(A), C& c, I& a ) {
    // The I here is a bit of a trick...if you use A in the constructor above instead of I
    // then it gets confused trying to deduce A as often the function arg and the input value
    // are different types (e.g. const int& as opposed to int). So fix A in the template
    // direction first, then pass it a type I which can be converted on the fly where needed.
    return BoundUnaryMemberFunction<C,A,R>( function, c, a );
}

template <typename C, typename A, typename R, typename I>
BoundUnaryMemberFunction<C,A,R> generateFunctionObject( R (C::*function)(A), C& c, const I& a ) {
    // This one differs from the previous due to the const reference - this allows things like
    // temporaries to pass through unscathed to a function with an argument like const int&.
    return BoundUnaryMemberFunction<C,A,R>( function, c, a );
}

} // namespace ecl

#endif /* ECL_UTILITIES_FUNCTION_OBJECTS_HPP_ */