Pointers to functions always interested me. I have made several classes along the years to deal with this question. With the TR1, we will have a standard way to create general functional pointers. So I have decided to implement the function class as defined in : [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf]
What is implemented here? * memfn * function * referencewrapper (simple case) * badfunctioncall (part of function definition) * bind is implemented partially
What is missing in this implementation? * referencewrapper is not complete. * resultof
The function class implemented here can be tested using the samples of the book: "The C++ Standard Library Extensions A Tutorial and Reference" - by Pete Becker The website contains the book samples: [[http://www.petebecker.com/tr1book/]]
Implementation:
Header: "typetraits.h" ( I have implemented just what I need now : isintegral )
#ifndef _TR1_TYPE_TRAITS
#define _TR1_TYPE_TRAITS
namespace std {
namespace tr1 {
template<class T> struct is_integral { static const bool value = false; };
template<> struct is_integral<bool> { static const bool value = true; };
template<> struct is_integral<char> { static const bool value = true; };
template<> struct is_integral<signed char> { static const bool value = true; };
template<> struct is_integral<unsigned char> { static const bool value = true; };
template<> struct is_integral<wchar_t> { static const bool value = true; };
template<> struct is_integral<short> { static const bool value = true; };
template<> struct is_integral<unsigned short> { static const bool value = true; };
template<> struct is_integral<int> { static const bool value = true; };
template<> struct is_integral<unsigned int> { static const bool value = true; };
template<> struct is_integral<long> { static const bool value = true; };
template<> struct is_integral<unsigned long> { static const bool value = true; };
template<> struct is_integral<long long> { static const bool value = true; };
template<> struct is_integral<unsigned long long> { static const bool value = true; };
}
}
#endif
}}}
Header: "functional"
C++0x implementation for function and mem_fn
{{{cpp
//
// Copyright (C) 2007, Thiago Adams (thiago.adams@gmail.com)
// This is the implementation of std::tr1::function proposed in tr1.
// See details in: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#ifndef TR1_FUNCTIONAL_HEADER
#define TR1_FUNCTIONAL_HEADER
#include <functional>
#include <cassert>
#include <typeinfo>
#include <stdexcept>
#include "type_traits"
namespace std {
namespace tr1 {
namespace detail
{
template <bool B, class T = void>
struct disable_if_c { typedef T type; };
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
}
//An exception of type bad_function_call is thrown by function::operator() ([3.7.2.4])
//when the function wrapper object has no target.
class bad_function_call : public std::runtime_error
{
public:
bad_function_call() : std::runtime_error("call to empty tr1::function") {}
};
template<class T> class reference_wrapper
{
public:
typedef T type;
explicit reference_wrapper(T& t): t_(&t) {}
operator T& () const { return *t_; }
T& get() const { return *t_; }
T* get_pointer() const { return t_; }
private:
T* t_;
};
//primary template
template<class T> struct const_mem_fn_t;
//primary template
template<class T> struct mem_fn_t;
//primary template
template<class T> struct mem_fn_t_binder;
//primary template
template<class T> struct const_mem_fn_t_binder;
//primary template
template<class F> class function;
struct unspecified_null_pointer_type {};
struct function_base
{
void *m_pInvoker;
function_base() : m_pInvoker(0)
{
}
bool empty() const
{
return m_pInvoker == 0;
}
};
// [3.7.2.7] Null pointer comparisons
template <class Function>
bool operator==(const function_base& f, unspecified_null_pointer_type *)
{
return !f;
}
template <class Function>
bool operator==(unspecified_null_pointer_type * , const function_base& f)
{
return !f;
}
template <class Function>
bool operator!=(const function_base& f, unspecified_null_pointer_type * )
{
return (bool)f;
}
template <class Function>
bool operator!=(unspecified_null_pointer_type *, const function_base& f)
{
return (bool)f;
}
// [3.7.2.8] specialized algorithms
template<class Function> void swap(function<Function>& a, function<Function>& b)
{
a.swap(b);
}
} //namespace tr1
} //namespace std
#define MACRO_JOIN(a, b) MACRO_DO_JOIN(a, b)
#define MACRO_DO_JOIN(a, b) MACRO_DO_JOIN2(a, b)
#define MACRO_DO_JOIN2(a, b) a##b
#define MACRO_MAKE_PARAMS1_0(t)
#define MACRO_MAKE_PARAMS1_1(t) t##1
#define MACRO_MAKE_PARAMS1_2(t) t##1, ##t##2
#define MACRO_MAKE_PARAMS1_3(t) t##1, ##t##2, ##t##3
#define MACRO_MAKE_PARAMS1_4(t) t##1, ##t##2, ##t##3, ##t##4
#define MACRO_MAKE_PARAMS1_5(t) t##1, ##t##2, ##t##3, ##t##4, ##t##5
#define MACRO_MAKE_PARAMS2_0(t1, t2)
#define MACRO_MAKE_PARAMS2_1(t1, t2) t1##1 t2##1
#define MACRO_MAKE_PARAMS2_2(t1, t2) t1##1 t2##1, t1##2 t2##2
#define MACRO_MAKE_PARAMS2_3(t1, t2) t1##1 t2##1, t1##2 t2##2, t1##3 t2##3
#define MACRO_MAKE_PARAMS2_4(t1, t2) t1##1 t2##1, t1##2 t2##2, t1##3 t2##3, t1##4 t2##4
#define MACRO_MAKE_PARAMS2_5(t1, t2) t1##1 t2##1, t1##2 t2##2, t1##3 t2##3, t1##4 t2##4, t1##5 t2##5
#define MACRO_MAKE_PARAMS1(n, t) MACRO_JOIN(MACRO_MAKE_PARAMS1_, n) (t)
#define MACRO_MAKE_PARAMS2(n, t1, t2) MACRO_JOIN(MACRO_MAKE_PARAMS2_, n) (t1, t2)
#define FUNC_NUM_ARGS 0
#include "functional_imp\function_imp.h"
#undef FUNC_NUM_ARGS
#define FUNC_NUM_ARGS 1
#include "functional_imp\function_imp.h"
#undef FUNC_NUM_ARGS
#define FUNC_NUM_ARGS 2
#include "functional_imp\function_imp.h"
#undef FUNC_NUM_ARGS
#define FUNC_NUM_ARGS 3
#include "functional_imp\function_imp.h"
#undef FUNC_NUM_ARGS
#define FUNC_NUM_ARGS 4
#include "functional_imp\function_imp.h"
#undef FUNC_NUM_ARGS
#define FUNC_NUM_ARGS 5
#include "functional_imp\function_imp.h"
#undef FUNC_NUM_ARGS
#endif //TR1_FUNCTIONAL_HEADER
Header: "function_imp.h"
Template especializations:
#if FUNC_NUM_ARGS == 0
#define FUNC_USE_COMMA_IF
#define CLASST1_CLASSTN
#define T1_TN void
#define T1t1_TNtn
#define t1_tn
#else
#define FUNC_USE_COMMA_IF ,
#define CLASST1_CLASSTN MACRO_MAKE_PARAMS1(FUNC_NUM_ARGS, class T)
#define T1_TN MACRO_MAKE_PARAMS1(FUNC_NUM_ARGS, T)
#define T1t1_TNtn MACRO_MAKE_PARAMS2(FUNC_NUM_ARGS, T, t)
#define t1_tn MACRO_MAKE_PARAMS1(FUNC_NUM_ARGS, t)
#endif
#if FUNC_NUM_ARGS == 1
#define USING_FUNCTION , std::unary_function<T1, Result>
#define USING_FUNCTIONM : public std::binary_function<T, T1, Result>
#elif FUNC_NUM_ARGS == 2
#define USING_FUNCTION , std::binary_function<T1, T2, Result>
#define USING_FUNCTIONM //: public std::binary_function<T1, T2, Result>
#else
#define USING_FUNCTION
#define USING_FUNCTIONM
#endif
namespace std {
namespace tr1 {
template<class Result, class T FUNC_USE_COMMA_IF CLASST1_CLASSTN>
struct const_mem_fn_t<Result (T::*) (T1_TN) const >
USING_FUNCTIONM
{
typedef Result result_type;
Result (T::*pMemberFunc) (T1_TN) const;
const_mem_fn_t(Result (T::*pf) (T1_TN) const) : pMemberFunc(pf)
{
}
Result operator ()(const T *f FUNC_USE_COMMA_IF T1t1_TNtn) const
{
return ((f->*pMemberFunc)(t1_tn));
}
Result operator ()(const T &f FUNC_USE_COMMA_IF T1t1_TNtn) const
{
return ((f.*pMemberFunc)(t1_tn));
}
};
template<class Result, class T FUNC_USE_COMMA_IF CLASST1_CLASSTN>
struct mem_fn_t<Result (T::*) (T1_TN) >
USING_FUNCTIONM
{
typedef Result result_type;
typedef Result (T::*pointer_type) (T1_TN);
Result (T::*pMemberFunc) (T1_TN);
mem_fn_t(Result (T::*pf) (T1_TN)) : pMemberFunc(pf)
{
}
Result operator ()(T *f FUNC_USE_COMMA_IF T1t1_TNtn)
{
return ((f->*pMemberFunc)(t1_tn));
}
Result operator ()(T &f FUNC_USE_COMMA_IF T1t1_TNtn)
{
return ((f.*pMemberFunc)(t1_tn));
}
};
template<class Result, class T FUNC_USE_COMMA_IF CLASST1_CLASSTN>
mem_fn_t<Result (T::*) (T1_TN)> mem_fn(Result (T::*pF) (T1_TN) )
{
return mem_fn_t<Result (T::*) (T1_TN)>(pF);
}
template<class Result, class T FUNC_USE_COMMA_IF CLASST1_CLASSTN>
const_mem_fn_t<Result (T::*) (T1_TN) const> mem_fn(Result (T::*pF) (T1_TN) const)
{
return const_mem_fn_t<Result (T::*) (T1_TN) const >(pF);
}
//bind partially implemented
//Allows to create function objects that holds "this"
//X x;
//f = bind(&X::F, x);
template<class Result, class T FUNC_USE_COMMA_IF CLASST1_CLASSTN>
struct const_mem_fn_t_binder<Result (T::*) (T1_TN) const>
{
const_mem_fn_t<Result (T::*) (T1_TN) const> m_f;
const T * m_p;
const_mem_fn_t_binder(Result(T::*PF)(T1_TN) const, const T & r)
: m_p(&r), m_f(PF)
{
}
const_mem_fn_t_binder(Result(T::*PF)(T1_TN) const, const T *p)
: m_p(p), m_f(PF)
{
}
Result operator ()(T1t1_TNtn) const
{
return m_f(m_p FUNC_USE_COMMA_IF t1_tn);
}
};
template<class Result, class T FUNC_USE_COMMA_IF CLASST1_CLASSTN>
struct mem_fn_t_binder<Result (T::*) (T1_TN) >
{
mem_fn_t<Result (T::*) (T1_TN)> m_f;
T * m_p;
mem_fn_t_binder(Result(T::*PF)(T1_TN), T & r)
: m_p(&r), m_f(PF)
{
}
mem_fn_t_binder(Result(T::*PF)(T1_TN), T *p)
: m_p(p), m_f(PF)
{
}
Result operator ()(T1t1_TNtn)
{
return m_f(m_p FUNC_USE_COMMA_IF t1_tn);
}
};
template<class Result, class T FUNC_USE_COMMA_IF CLASST1_CLASSTN>
mem_fn_t_binder<Result(T::*)(T1_TN)> bind(Result(T::*PF)(T1_TN), T &r)
{
return mem_fn_t_binder<Result(T::*)(T1_TN)>(PF, r);
}
template<class Result, class T FUNC_USE_COMMA_IF CLASST1_CLASSTN>
const_mem_fn_t_binder<Result(T::*)(T1_TN) const> bind(Result(T::*PF)(T1_TN) const, T &r)
{
return const_mem_fn_t_binder<Result(T::*)(T1_TN) const>(PF, r);
}
template<class Result, class T FUNC_USE_COMMA_IF CLASST1_CLASSTN>
mem_fn_t_binder<Result(T::*)(T1_TN)> bind(Result(T::*PF)(T1_TN), T *p)
{
return mem_fn_t_binder<Result(T::*)(T1_TN)>(PF, p);
}
template<class Result, class T FUNC_USE_COMMA_IF CLASST1_CLASSTN>
const_mem_fn_t_binder<Result(T::*)(T1_TN) const> bind(Result(T::*PF)(T1_TN) const, T *p)
{
return const_mem_fn_t_binder<Result(T::*)(T1_TN) const>(PF, p);
}
// Function type Result (T1, T2, ..., TN), 0 <= N <= Nmax
template<class Result FUNC_USE_COMMA_IF CLASST1_CLASSTN>
class function <Result (T1_TN)> : public function_base
USING_FUNCTION
{
struct invoker_base
{
virtual ~invoker_base(){}
virtual Result invoke(T1_TN) = 0;
virtual invoker_base * clone() const = 0;
virtual void * get_ptr( const type_info & ) const = 0;
virtual const type_info & get_type_info() const = 0;
};
template<class T>
struct invoker : public invoker_base
{
typedef T target_type;
target_type m_functor_object;
invoker_base * clone() const
{
return new invoker(*this);
}
const type_info & get_type_info() const
{
return typeid(target_type);
}
void * get_ptr( const type_info & ti) const
{
if (typeid(target_type) == ti)
return (void*) &m_functor_object;
return 0;
}
Result invoke(T1t1_TNtn)
{
return m_functor_object(t1_tn);
}
invoker(const target_type & object)
: m_functor_object(object)
{
}
};
template <class T> void new_invoker( const T &object )
{
m_pInvoker = new invoker<T>(object);
}
template<class T> void new_invoker( Result (T::*pmFunction) (T1_TN) )
{
if (pmFunction == 0)
return;
typedef mem_fn_t<Result (T::*)(T1_TN)> functor;
m_pInvoker = new invoker< functor >( functor(pmFunction) );
}
public:
typedef Result result_type;
// [3.7.2.1] construct/copy/destroy
explicit function() : function_base()
{
assert(!*this);
}
function(const function& f)
{
if (f.m_pInvoker != 0)
m_pInvoker = ((invoker_base*)(f.m_pInvoker))->clone();
assert( (!*this && !f) || (*this && f));
}
function(unspecified_null_pointer_type *) : function_base()
{
assert(!*this);
}
//enable_if here is to disable create function objects of integral types.
// so is possible to initialize do 0 function f(0);
template<class F>
function(const F &f
,typename detail::disable_if<is_integral<F> , int>::type = 0
)
{
new_invoker(f);
}
function& operator=(const function& f)
{
function(f).swap(*this);
return *this;
}
function& operator=(unspecified_null_pointer_type * )
{
delete ((invoker_base*)m_pInvoker);
m_pInvoker = 0;
assert(!*this);
return *this;
}
template<class F>
typename detail::disable_if< is_integral<F> , function >::type &
operator=(const F &f)
{
function(f).swap(*this);
return *this;
}
template<class F> function& operator=(reference_wrapper<F> f)
{
function(f).swap(*this);
return *this;
}
~function()
{
delete ((invoker_base*)m_pInvoker);
}
// [3.7.2.2] function modifiers
void swap(function& f)
{
std::swap(m_pInvoker, f.m_pInvoker);
}
// [3.7.2.3] function capacity
operator bool() const throw()
{
return !empty();
}
// [3.7.2.4] function invocation
Result operator()(T1t1_TNtn) const
{
if (!*this)
throw bad_function_call();
return ((invoker_base*)m_pInvoker)->invoke(t1_tn);
}
// [3.7.2.5] function target access
const std::type_info& target_type() const
{
if (!*this)
return typeid(void);
return ((invoker_base*)m_pInvoker)->get_type_info();
}
template <typename T> T* target()
{
if (!*this)
return 0;
return (T*)((invoker_base*)m_pInvoker)->get_ptr(typeid(T));
}
template <typename T> const T* target() const
{
if (!*this)
return 0;
return ((invoker_base*)m_pInvoker)->get_ptr(typeid<T>);
}
private:
// [3.7.2.6] undefined operators
template<class Function> bool operator==(const function<Function>&);
template<class Function> bool operator!=(const function<Function>&);
};
} // namespace tr1
} // namespace std
#undef CLASST1_CLASSTN
#undef T1_TN
#undef T1t1_TNtn
#undef t1_tn
#undef FUNC_USE_COMMA_IF
#undef USING_FUNCTION
#undef USING_FUNCTIONM
My implementation of std::tr1::shared_ptr sharedptr.htm