Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use a functor to replace the lambda one? #11

Closed
douyw opened this issue May 22, 2015 · 4 comments · Fixed by #42
Closed

How to use a functor to replace the lambda one? #11

douyw opened this issue May 22, 2015 · 4 comments · Fixed by #42

Comments

@douyw
Copy link

douyw commented May 22, 2015

Hello,
Thank you for this great sqlite wrapper! It's very convenient.
While using the wrapper is delightful, a problem about eliminating similar code occurs.

The functor:

struct ItemResultHandler {
    explicit ItemResultHandler(QVariantMap& map_) : map(map_) {}
    void operator() ( int id, std::string name, double price, int qty ) {
         map.insert("id", id);
         map.insert("name", QString::fromStdString(name));   
         map.insert("price", price);
         map.insert("qty", qty);
    }
    QVariantMap& map;
};

The code:

QVariantMap getItemById(int id) {
  QVariantMap map;
  database db(dbfile);
  db << "select id,name,price,qty from items where id=?"
     << id 
     >> ItemResultHandler(map);
  return map;
}

It has compiling errors:

../../myapp/src/utility/function_traits.h:12: error: type 'void (ItemResultHandler::*)(std::__1::basic_string<char>, std::__1::basic_string<char>, int, int)' cannot be used prior to '::' because it has no members
        decltype(&Function::operator())
                  ^
 ../../myapp/src/sqlite_modern_cpp.h:218: error: incomplete definition of type 'sqlite::utility::function_traits<ItemResultHandler>'
                        binder<traits::arity>::run(*this, func);
                               ~~~~~~^~

I have posted a question in SO. Could you please have a look at it? Thank you in advance.
http://stackoverflow.com/questions/30387896/how-to-eliminate-multiple-similar-sql-queries-with-one-resultset-hander

@douyw douyw changed the title How to eliminate similar sql queries? How to use a functor to replace the lambda one? May 22, 2015
@Killili
Copy link
Collaborator

Killili commented May 22, 2015

Hi, its a problem with mapping all those different result types we handle. So the Template got a bit complex and it looks like it does not handle this case. The new one has a more specific error but still does not handle this case.

Here is an example how you could do it with the type extensions.

    // The thing you want
    struct Item {
        int id;
        string name;
        double price;
        int qty;
    };
    // to get it back we need to give a deserialization method:
    namespace sqlite {
        template<> void get_col_from_db(database_binder& db, int inx, ::Item*& ret) {   // specify the type it will be used on, a pointer is necessary if you’re type has no default constructor. Otherwise a object ref does the job too.
            ret = new Item();
            get_col_from_db(db, inx++, ret->id);
            get_col_from_db(db, inx++, ret->name);
            get_col_from_db(db, inx++, ret->price);
            get_col_from_db(db, inx++, ret->qty);
        }
    }

    {// usage
        Item* item;
        db << "select val,name,price,qty from test" >> item;
        std::cout << item->name;
        delete item;
    }

But this is ugly and definitely needs to change, i will get rid of this pointer mess in the next Version.

@Killili
Copy link
Collaborator

Killili commented May 22, 2015

There is however a shorter version, just convert youre functor to a lambda in this way:

auto ItemResultHandler = [](Item& item) -> std::function<void(int, std::string , double , int )> {
    return [&item](int id, std::string name, double price, int qty) mutable {
        item.id = id;
        item.name = name;
        item.price = price;
        item.qty = qty;
    };
};

and just use it like this:

Item item;
db << "select val,name,price,qty from test" >> ItemResultHandler(item);

@douyw
Copy link
Author

douyw commented May 23, 2015

I used the shorter version, and wrap the code in a factory function, something like MakeItemResultHandler.
You are a hero! Thank you very much!

@aminroosta
Copy link
Collaborator

@Killili please review https://github.com/aminroosta/sqlite_modern_cpp/pull/42
I don't have access to MSVC, could please also check on VS 2015.

@aminroosta aminroosta reopened this Mar 26, 2016
aminroosta added a commit that referenced this issue Mar 26, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants