Home > Net >  Emulate std::function functionality
Emulate std::function functionality

Time:01-14

I'm trying to emulate the std::function functionality below, but I'm running into the following error

class Player
{
public:
void move_to(Point location);
};
std::function<void(Player&, Point)> fun = &Player::move_to;
Player hero;
fun(hero, point{ 2, 4 });
fp.cc:32:33: error: variable ‘fun<void(Player&, Point)> f’ has initializer but incomplete type
   32 |    fun<void(Player &, Point p)> f = &Player::move_to;

#include <iostream>

using namespace std;
template <typename T>
struct fun;

template <typename Ret, typename T, typename ...Args>
struct fun <Ret(*)(T&, Args...)>{
   char *data;
   using fptr = Ret(T::*)(Args...);
   fun(fptr p) : data(p) {}
   Ret operator()(T &t, Args... args) {
      if (std::is_same_v<Ret, void>) {
         (t.*((fptr)data))(args...);
      }
      return (t.*((fptr)data))(args...); 
   }
};

struct Point {
   int x;
   int y;
};

struct Player {
   void move_to(Point p) {
      cout << __PRETTY_FUNCTION__ << endl;
   }
};

int main() {
   fun<void(Player &, Point p)> f = &Player::move_to;
   Point p{1,2};
   Player pl;
//   f(pl, p);
}

CodePudding user response:

Your code is close but has a couple small errors:

  • You have only provided a definition of fun for Ret(*)(T&, Args...), but fun<void(Player &, Point p)> does not match this template. So I removed the (*) which is not really required in your specialization.

  • A function pointer is not convertible to/from char *, so I changed the type of data to be fptr so it matches the argument type.

godbolt link

#include <iostream>

using namespace std;
template <typename T>
struct fun;

template <typename Ret, typename T, typename ...Args>
struct fun <Ret(T&, Args...)>{
   using fptr = Ret(T::*)(Args...);
   fptr data;
   fun(fptr p) : data(p) {}
   Ret operator()(T &t, Args... args) {
      if (std::is_same_v<Ret, void>) {
         (t.*((fptr)data))(args...);
      }
      return (t.*((fptr)data))(args...); 
   }
};

struct Point {
   int x;
   int y;
};

struct Player {
   void move_to(Point p) {
      cout << __PRETTY_FUNCTION__ << endl;
   }
};

int main() {
   fun<void(Player &, Point p)> f = &Player::move_to;
   Point p{1,2};
   Player pl;
   f(pl, p);
}
  •  Tags:  
  • Related