ChrisPeterson
ChrisPeterson

Reputation: 419

Generalizing a function that returns a callable based on an object and a class method

I am trying to write a template function that returns a callable object based on an object and a class method. The idea is:

class Obj : public boost::enable_shared_from_this<Obj>
{
public:

    bool Meth1(int a)    { return a == 7; }
    int  Meth2(double a) { return a * 2;  }
};

template<class Tobj, typename Tmeth>
auto Creator(boost::shared_ptr<TObj> shobj, Tmeth meth) -> decltype("callable based on Tmeth")
{
    return boost::bind(&meth, shobj, _1);
}

The usage would be something like:

boost::shared_ptr<Obj> obj = boost::make_shared<Obj>();

// mm would be of type boost::function<bool(int)>
auto mm = Creator(obj->shared_from_this(), Obj::Meth1);

bool isSeven = mm(7);

I cannot find a way of doing this. As a fun fact, while experimenting, one of my desperate tries was something like:

template<class Tobj, typename Tmeth>
auto return_mm(Tobj &obj, Tmeth meth) 
     -> decltype(boost::bind(&meth, obj.shared_from_this(), _1))
{
     return boost::bind(&meth, obj.shared_from_this(), _1);
}

I know, looks silly and it makes the VC++10 to crash. Any idea? Maybe should I use boost::phoenix?

Update:

This compiles and works on VC++10 but, seriously, looks awfull:

template<typename TOBJ, typename TMETH>
auto Create(boost::shared_ptr<TOBJ> sobj, TMETH mm) -> decltype( boost::bind(mm, sobj, _1) )
{
    return boost::bind(mm, sobj, _1);
}

The part " -> decltype( boost::bind(mm, sobj, _1) )" does not look good to me. Also if you try to use it with a method expecting two parameters it breaks the compiler!

Upvotes: 1

Views: 118

Answers (1)

Dmitry Sokolov
Dmitry Sokolov

Reputation: 3180

Fixed some errors in your code

Updated. Added boost::function example.

class Obj : public boost::enable_shared_from_this<Obj>
{
public:
    bool Meth1(int a)    { return a == 7; }
    int  Meth2(double a) { return a * 2;  }
};

template<class Tobj, typename Tmeth>
auto Creator(boost::shared_ptr<Tobj> shobj, Tmeth meth)
{
    return boost::bind(meth, shobj, _1);
}

template<typename Targ, class Tobj, typename Tmeth>
boost::function<bool (Targ)> Creator2(boost::shared_ptr<Tobj> shobj, Tmeth meth)
{
    return boost::bind(meth, shobj, _1);
}

int main() {
    boost::shared_ptr<Obj> obj = boost::make_shared<Obj>();

    // mm would be of type boost::function<bool(int)>
    auto mm = Creator(obj->shared_from_this(), &Obj::Meth1);
    boost::function<bool (int)> mm2 = Creator2<int>(obj->shared_from_this(), &Obj::Meth1);

    bool isSeven = mm(7);
    cout << isSeven << endl;
    cout << mm2(7) << endl;
    return 0;
}

Result on Ideone.com

Upvotes: 0

Related Questions