I am going to use MySQL connector. They provide functions to access the result row. Some examples are getString(1)
, getInt(1)
, getDate(2)
. The number inside the parenthesis is about the index of the result.
So that I have to use the following code to access this example row: 'John', 'M', 34
string name = row.getString(1);
string sex = row.getString(2);
int age = row.getInt(3);
I would like to try generic programming for various reasons (mainly for fun). But it was quite disappointing that I can't make it happens even with much time used.
The final result that I want:
std::tie<name, sex, age> = row.getResult<string, string, int>();
This functions should call the corresponding MySQL API.
It is also good to see any answer similar to below, although the syntax is wrong.
std::tie<name, sex, age> = row.getResult([string, string, int]);
Please don't suggest using for-loop. Let's try something more generic & functional ;-)
This works for me:
struct Row
{
template <int N, typename ... Args> struct Helper;
template <typename Arg1> struct Helper<1, Arg1>
{
static std::tuple<Arg1> getResult(Row& r)
{
return std::make_tuple(r.getResult<Arg1>(0));
}
};
template <int N, typename Arg1, typename ... Args>
struct Helper<N, Arg1, Args...>
{
static std::tuple <Arg1, Args ...> getResult(Row& r)
{
return std::tuple_cat(std::make_tuple(r.getResult<Arg1>(N-1)),
Helper<N-1, Args...>::getResult(r));
}
};
template <typename Arg> Arg getResult(int index)
{
// This is where the value needs to be extracted from the row.
// It is a dummy implementation for testing purposes.
return Arg{};
}
template <typename ... Args>
std::tuple <Args ...> getResult()
{
return Helper<sizeof...(Args), Args...>::getResult(*this);
}
};
Example usage:
Row r;
auto res1 = r.getResult<std::string>();
auto res2 = r.getResult<int>();
auto res3 = r.getResult<int, double, int>();
auto res4 = r.getResult<int, int, double, double>();
auto res5 = r.getResult<std::string, std::string, int, int, double, double>();
Working code: http://ideone.com/6IpJ8q