|
Boost Users : |
Subject: Re: [Boost-users] [Tuple] Help getting started with Tuple-based meta-programming
From: Dominique Devienne (ddevienne_at_[hidden])
Date: 2009-03-20 16:59:54
On Fri, Mar 20, 2009 at 3:01 PM, Steven Watanabe <watanabesj_at_[hidden]> wrote:
> In this case, I think Boost.Fusion can help (warning untested).
>
> #include <boost/fusion/include/for_each.hpp>
> #include <boost/fusion/include/boost_tuple.hpp>
>
> struct get_t {
> ResultSet& r;
> int& n;
> template<class T>
> void operator()(T& t) const {
> t = r.get<T>(n++);
> }
> };
>
> template<Row>
> void get_rows(const char* query, std::vector<Row>& out) {
> ResultSet rset = sql_exec(query);
> while(rset.hasMoreRows()) {
> Row row;
> int n = 0;
> get_t getter = { rset, n };
> boost::fusion::for_each(row, getter);
> out.push_back(row);
> }
> }
Simply amazing Steven :) Thanks a lot!
Here's the code I ended up with, which reveals more context.
Many thanks. I can't believe the quality and speed of your answer frankly.
You made me day. Sincerely, --DD
#include <sqlite3pp.h>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
...
// Courtesy Steven Watanabe, Mar 20, 2009, boost-users mailing list.
struct get_rows_binder {
sqlite3pp::query& qry;
int& bind_idx;
template <class T> void operator()(const T& t) const {
qry.bind(bind_idx++, t);
}
};
struct get_rows_getter {
sqlite3pp::query::iterator& i;
int& col_idx;
template <class T> void operator()(T& t) const {
t = i->get<T>(col_idx++);
}
};
template <class ROW, class BIND> void get_rows(
const char* query, const BIND& binds, std::vector<ROW>& out
) {
sqlite3pp::database& conn = DBConnection::instance()->db();
sqlite3pp::query qry(conn);
checkerr(conn, qry.prepare(query));
if (boost::tuples::length<BIND>::value > 0) {
int bind_idx = 1; // 1-based for binds
get_rows_binder binder = { qry, bind_idx };
boost::fusion::for_each(binds, binder);
}
for (sqlite3pp::query::iterator i = qry.begin(); i != qry.end(); ++i) {
ROW row;
int col_idx = 0; // 0-based for result-set columns
get_rows_getter getter = { i, col_idx };
boost::fusion::for_each(row, getter);
out.push_back(row);
}
}
template <class ROW> void get_rows(const char* query, std::vector<ROW>& out) {
get_rows(query, boost::make_tuple(), out);
}
void TypeIdTests::test_rtti_vtable() {
...
{
typedef boost::tuple<sqlite_int64> Row;
std::vector<Row> rset;
get_rows("select count(*) from rtti", rset);
CPPUNIT_ASSERT_EQUAL(1, (int)rset.size());
CPPUNIT_ASSERT_EQUAL(expected_count, boost::get<0>(rset[0]));
}
{
typedef boost::tuple<unsigned short, unsigned short, unsigned
short> Row;
std::vector<Row> rset;
get_rows(
"select type, is_a, distance from rtti where type = :1 and
is_a = :2",
boost::make_tuple(ts.transient_id(), ag.transient_id()), rset
);
CPPUNIT_ASSERT_EQUAL(1, (int)rset.size());
CPPUNIT_ASSERT_EQUAL(ts.transient_id(), boost::get<0>(rset[0]));
CPPUNIT_ASSERT_EQUAL(ag.transient_id(), boost::get<1>(rset[0]));
CPPUNIT_ASSERT_EQUAL(unsigned short(1), boost::get<2>(rset[0]));
}
}
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net