N
Noah Roberts
A while back I posted a question either here or to the boost user list
about how to iterate through a vector of strings and perform a lexical
cast on them into elements of a tuple. I was working with sqlite3 and
found myself repeatedly writing code like so:
t.get<0>() = boost::lexical_cast<double>(vect[0]);
t.get<1>() = boost::lexical_cast<int>(vect[1]);
....
For each query I would invent. Certainly there seemed there should be a
way to use metaprogramming to approach this problem. I could get here:
However, I couldn't figure how to insert that into a metaprogram. I
figured it would have something to do with for_each but couldn't figure
it out. When I approached whatever list I posted my question to I was
sent to some library...I forget which one but it wasn't the answer.
Well, last night a light in my brain turned on. It's actually very
simple once it dawns on one how to do it:
template < typename TUPLE >
struct tuple_assign
{
TUPLE & t;
std::vector< std::string > const& data;
tuple_assign(TUPLE & to, std::vector<std::string> const& from) :
t(to), data(from) {}
template < typename T>
void operator() (T) // T must be an mpl::int_
{
boost::tuples::get<T::value>(t) =
boost::lexical_cast< boost::tuples::element<T::value,
TUPLE>::type>(data[T::value]);
}
};
Your calling code looks like so:
boost::tuple<double, int, std::string> t;
std::vector<std::string> d;
d += "5.2","42","HELLO!";
boost::mpl::for_each< boost::mpl::range<0,3> >(tuple_assign<
boost::tuple<double,int,std::string> >(t,d));
The range can also be derived through the template system like so:
boost::mpl::range< 0,
boost::tuples::length<boost::tuple<double,int,std::string> >
Much safety can be placed on this system. I haven't done so here. This
problem solved though, there's nothing stopping a generic query
interface that could be used something like so:
tie(x, y, z) = query.run();
as well as an iterative interface that provides a similar tuple interface.
about how to iterate through a vector of strings and perform a lexical
cast on them into elements of a tuple. I was working with sqlite3 and
found myself repeatedly writing code like so:
t.get<0>() = boost::lexical_cast<double>(vect[0]);
t.get<1>() = boost::lexical_cast<int>(vect[1]);
....
For each query I would invent. Certainly there seemed there should be a
way to use metaprogramming to approach this problem. I could get here:
t.get said:>(vect[N]);
However, I couldn't figure how to insert that into a metaprogram. I
figured it would have something to do with for_each but couldn't figure
it out. When I approached whatever list I posted my question to I was
sent to some library...I forget which one but it wasn't the answer.
Well, last night a light in my brain turned on. It's actually very
simple once it dawns on one how to do it:
template < typename TUPLE >
struct tuple_assign
{
TUPLE & t;
std::vector< std::string > const& data;
tuple_assign(TUPLE & to, std::vector<std::string> const& from) :
t(to), data(from) {}
template < typename T>
void operator() (T) // T must be an mpl::int_
{
boost::tuples::get<T::value>(t) =
boost::lexical_cast< boost::tuples::element<T::value,
TUPLE>::type>(data[T::value]);
}
};
Your calling code looks like so:
boost::tuple<double, int, std::string> t;
std::vector<std::string> d;
d += "5.2","42","HELLO!";
boost::mpl::for_each< boost::mpl::range<0,3> >(tuple_assign<
boost::tuple<double,int,std::string> >(t,d));
The range can also be derived through the template system like so:
boost::mpl::range< 0,
boost::tuples::length<boost::tuple<double,int,std::string> >
Much safety can be placed on this system. I haven't done so here. This
problem solved though, there's nothing stopping a generic query
interface that could be used something like so:
tie(x, y, z) = query.run();
as well as an iterative interface that provides a similar tuple interface.