How to pass a method pointer as a template parameter

I am trying to write code that calls the class method specified as a template parameter. To simplify, you can assume that the method has a single parameter (of an arbitrary type) and returns void. The goal is to avoid the pattern in the calling site without typing the parameter type. Here is a sample code:

template <class Method> class WrapMethod {
  public:
   template <class Object>
   Param* getParam() { return &param_; }
   Run(Object* obj) { (object->*method_)(param_); }
  private:
    typedef typename boost::mpl::at_c<boost::function_types::parameter_types<Method>, 1>::type Param;
    Method method_;
    Param param_
};

Now, in the calling site, I can use this method without writing the parameter type.

Foo foo;
WrapMethod<BOOST_TYPEOF(&Foo::Bar)> foo_bar;
foo_bar.GetParam()->FillWithSomething();
foo_bar.Run(foo);

So this code works, and that is almost what I want. The only problem is that I want to get rid of the BOOST_TYPEOF macro on the calling site. I would like to write something like WrapMethod<Foo::Bar> foo_barinstead WrapMethod<BOOST_TYPEOF(&Foo::Bar)> foo_bar.

, , , ( WrapMethod - ) , typeof.

, , , .

, : typemame Param . , FillWithSomething WrapMethod ( ). Param Param, . , , , BOOST_TYPEOF ( WrapMethod , , api , ).

:

, . , - WrapMethod<&Foo::Bar>, , . , ( ), . , - typeof_literal<0>::type, int typeof_literal<&Foo::Bar>::type, void (Foo*::)(Param) . , BOOST_TYPEOF, declype , . , :

template <template<class T> T value> struct typeof_literal {
  typedef decltype(T) type; 
};

++ 0x, ( BOOST_AUTO), auto -:

template <class T> WrapMethod<T> GetWrapMethod(T) { return WrapMethod<T>(); }
auto foo_bar = GetWrapMethod(&Foo::Bar);
+3
5

decltype, decltype:

WrapMethod<decltype(&Foo::Bar)> foo_bar;

EDIT: , , ++ 0x:

template <class T> WrapMethod<T> GetWrapMethod(T) { return WrapMethod<T>(); }
auto foo_bar= GetWrapMethod(&Foo::Bar);

EDIT2: , , , , ++, :

#define WrapMethodBlah(func) WrapMethod<decltype(func)>
+2

:

template <typename Object, typename Param, void (Object::*F)(Param)> 
class WrapMethod { 
public: 
   Param* getParam() { return &param_; } 
   void Run(Object* obj) { (obj->*F)(param_); } 

private: 
    Param param_;
}; 

Foo foo; 
WrapMethod<Foo, Param, &Foo::Bar> foo_bar;       
foo_bar.getParam()->FillWithSomething();
foo_bar.Run(foo);

EDIT: , - :

template <typename Foo, typename Param>
void call(Foo& obj, void (Foo::*f)(Param))
{
    Param param;
    param.FillWithSomthing();
    obj.*f(param);
}

:

Foo foo;
call(foo, &Foo::Bar);

2nd EDIT: :

template <typename Foo, typename Param>
void call(Foo& obj, void (Foo::*f)(Param), void (Param::*init)())
{
    Param param;
    param.*init();
    obj.*f(param);
}

:

Foo foo;
call(foo, &Foo::Bar, &Param::FillWithSomething);
+3

?

 template <typename T> void method(T & param)
 {
   //body
 }

           int i;
           bool b;

           method(i);
           method(b);

           method<int>(i);

You can provide specializations for different types of data.

           template <> void method<int>(int param)
           {
               //body
           }
0
source

If you already allow it BOOST_TYEPOF(), use BOOST_AUTO()with the object generator function to enable type inference:

template<class Method> WrapMethod<Method> makeWrapMethod(Method mfp) {
    return WrapMethod<Method>(mfp);
}

BOOST_AUTO(foo_bar, makeWrapMethod(&Foo::Bar));
0
source

Ok, let's get this over with.

First of all, note that the output of the template parameter is available (as indicated in several answers) with functions.

So, here is the implementation (view):

// WARNING: no virtual destructor, memory leaks, etc...

struct Foo
{
  void func(int e) { std::cout << e << std::endl; }
};

template <class Object>
struct Wrapper
{
  virtual void Run(Object& o) = 0;
};

template <class Object, class Param>
struct Wrap: Wrapper<Object>
{
  typedef void (Object::*member_function)(Param);

  Wrap(member_function func, Param param): mFunction(func), mParam(param) {}

  member_function mFunction;
  Param mParam;

  virtual void Run(Object& o) { (o.*mFunction)(mParam); }
};

template <class Object, class Param>
Wrap<Object,Param>* makeWrapper(void (Object::*func)(Param), Param p = Param())
{
  return new Wrap<Object,Param>(func, p);
}


int main(int argc, char* argv[])
{
  Foo foo;
  Wrap<Foo,int>* fooW = makeWrapper(&Foo::func);
  fooW->mParam = 1;
  fooW->Run(foo);

  Wrapper<Foo>* fooW2 = makeWrapper(&Foo::func, 1);
  fooW2->Run(foo);
  return 0;
}

I think using a base class is a native C ++ way to hide information by type of erase.

0
source

Source: https://habr.com/ru/post/1753814/


All Articles