views:

61

answers:

1

Hi, I am trying to write an iterator class which returns a getter function return value when it is dereferenced. The code works fine, my only problem is that I would like to write the member_ptr_functor using only one template parameter and not 3, since I am supposed to be able to deduce the types of the argument and return value from the member function type. I think the problematic one is the argument type, I tried using boost::remove_ptr&, but I couldn't compile it.

#include <iostream>
#include <vector>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
using namespace boost;
using namespace std;

class CTest
{
private:
    int m_x;

public:
    CTest(int x) : m_x(x)
    {
    }

    const int& GetX() const
    {
        return m_x;
    }

};

template<typename MemFunType, typename ArgumentType, typename ResultType>
class member_ptr_functor : public unary_function<ArgumentType, ResultType>
{
private:
    MemFunType m_MemFun;

public:
    typedef ArgumentType argument_type;
    typedef ResultType result_type;

    member_ptr_functor(MemFunType MemFun) : m_MemFun(MemFun)
    {
    }

    result_type operator() (argument_type arg) const
    {
        return m_MemFun(&arg);
    }
};

template<typename MemFunType, typename ArgumentType, typename ResultType>
member_ptr_functor<MemFunType, ArgumentType, ResultType> make_member_ptr_functor(MemFunType MemFun)
{
    return member_ptr_functor<MemFunType, ArgumentType, ResultType>(MemFun);
}

class CPrintFunctor : public unary_function<int, void>
{
public:
    void operator() (const int n) const
    {
        cout << n << endl;
    }
};

int main()
{
    typedef vector<CTest> Container_t;
    Container_t v;
    v.push_back(CTest(1));

    CPrintFunctor PF;
    Container_t::const_iterator itStart = v.begin();
    Container_t::const_iterator itEnd = v.end();

    typedef member_ptr_functor<const_mem_fun_t<const int&, CTest> , CTest, const int&> member_ptr_functor_t;
    member_ptr_functor_t MemberPtrFunctor =     member_ptr_functor_t(mem_fun(&CTest::GetX));

    typedef transform_iterator<member_ptr_functor_t, Container_t::const_iterator, const int&, const int> transform_iterator_t;
    transform_iterator_t itTransformStart = make_transform_iterator(itStart, MemberPtrFunctor);
    transform_iterator_t itTransformEnd = make_transform_iterator(itEnd, MemberPtrFunctor);

    for_each(itTransformStart, itTransformEnd, PF);

    return 0;
}

Hagai.

A: 

This does not answer your question directly but rather suggests alternative approach.

You are already using Boost, so why do you not take it one step further, use Boost.Range:

#include <boost/functional.hpp>
#include <boost/range.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/transformed.hpp>

// ... 

int main ()
{
  // ...
  boost::range::for_each (
    boost::adaptors::transform (v, boost::mem_fun_ref (&CTest::GetX)),
    PF);
}

This lets you write the functionality that you want without having to define own functors and without using too many typedefs.

wilx
Thanks for the answer.I am not familiar with boost.range, and it could be a good long term solution. However, the code I provided is just an example, I actually need the iterator for other stuff in my code.