0

I am trying to code a tiny C++ Sql ORM based on the Data Mapper design pattern. I m playing with template and metaprogramming to get introspection features. I can't do it after several tries..

From the mapper, I would like to map column names with getter method from the object I want to store in .
Let see an example :

   class User
    {
    public :
        int age() {
            cout<<"int\n";
            return 5;
        }

        float size(){
            cout<<"float\n";
            return 4.2;
        }
    }; 

I would like a Mapper class which make me possible to bind column with method:

Mapper<User> mapper;
mapper.bind("age", &User::age);
mapper.bind("size", &User::size);

So I can write on my database like this :

 Mapper::insert(User * user) 
{
      //bindNames = {"size", "age"}
     for (const auto&  field : bindsNames) 
      {
         // Generate 
         Query q("INSERT into users (name, age) VALUES(:name, :age)");
         q.repace(":size", (user->*readSizeFct)();
         q.repace(":age", (user->*readAgeFct)();
      }

}

After several tries, the main problem is I cannot store a list of function pointer dynamically with different signature...

Do you have any suggestion to make my tiny ORM working ? I guess I have to read documentation about template metaprogramming ...

DrIDK
  • 7,642
  • 2
  • 14
  • 14

1 Answers1

1

You could do something like

template<typename C, typename F>
void Mapper<C>::bind(const std::string& name, F f)
{
  m_getters[name] = [f](Query& q, const std::string& param, C* c)
  {
   q.replace(param, (c->*f)());
  };
}

with std::map<std::string, std::function<void(Query&, const std::string&, C*)>> m_getters.

That way you erase the type of your getter function and can still call the correct overload for Query::replace

ACB
  • 1,607
  • 11
  • 31
  • Thanks for your reply . So this example was for getter. What about setter method ? – DrIDK Sep 04 '18 at 21:04
  • setter would work pretty much the same. Only that you wold do something like `(c->*f)(q.extract(param));` to extract the value from the query and then call the setter with it. You can get the type of the value through deduction. See for example https://stackoverflow.com/questions/9065081/how-do-i-get-the-argument-types-of-a-function-pointer-in-a-variadic-template-cla . By the way you can also get the address of member variables directly which would remove the need to write explicit getters and setters for every type. – ACB Sep 05 '18 at 08:16