Created
August 10, 2013 15:57
-
-
Save mpapierski/6200965 to your computer and use it in GitHub Desktop.
sql-like syntax for standard library containers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <boost/tuple/tuple.hpp> | |
#include <boost/utility.hpp> | |
#include <vector> | |
#include <boost/typeof/typeof.hpp> | |
#include <boost/foreach.hpp> | |
struct person | |
{ | |
int id_; | |
std::string first_name_; | |
std::string last_name_; | |
person(int id, std::string first_name, std::string last_name) | |
: id_(id) | |
, first_name_(first_name) | |
, last_name_(last_name) | |
{ | |
} | |
}; | |
/** | |
* Convert pointer to member variable to its type. | |
* Example: | |
* std::string Class::* returns T. | |
* We don't need implementation because we only use it in expression | |
* which is OK to calculate result type. | |
*/ | |
template <typename T, typename Cls> | |
T process_member_variable(T Cls::*input); | |
/** | |
* Wrapper around our type process function. | |
* Calculates result of expression that yields actual type of pointer to | |
* member variable. | |
* type_from_member<T Cls::*>::type is T | |
*/ | |
template <typename T> | |
struct type_from_member | |
{ | |
typedef BOOST_TYPEOF(process_member_variable(T())) type; | |
}; | |
template <typename FromT, typename T1> | |
struct select_impl | |
{ | |
FromT from_obj_; | |
T1 t1_; | |
typedef typename type_from_member<T1>::type arg1_type; | |
select_impl(FromT from_obj, T1 t1) | |
: from_obj_(from_obj) | |
, t1_(t1) | |
{} | |
std::vector<boost::tuple<arg1_type> > to_vector() | |
{ | |
typedef typename FromT::value_type::iterator iter_type; | |
std::vector<boost::tuple<arg1_type> > results; | |
for (iter_type it = from_obj_.input_.begin(); it != from_obj_.input_.end(); ++it) | |
{ | |
const arg1_type & arg1 = (*it).*t1_; | |
results.push_back(boost::make_tuple(arg1)); | |
} | |
return results; | |
} | |
}; | |
template <typename T> | |
struct from_impl | |
{ | |
typedef from_impl<T> this_type; | |
typedef T value_type; | |
T & input_; | |
from_impl(T & input) | |
: input_(input) | |
{ | |
} | |
template <typename F1> | |
select_impl<this_type, F1> select(F1 f1) | |
{ | |
return select_impl<this_type, F1>(*this, f1); | |
} | |
}; | |
template <typename T> | |
from_impl<T> from(T & input) { return from_impl<T>(input); } | |
int | |
main() | |
{ | |
std::vector<person> vec; | |
vec.push_back(person(1, "first name 1", "last name 1")); | |
vec.push_back(person(2, "first name 2", "last name 2")); | |
// make query | |
std::vector<boost::tuple<std::string> > out = | |
from(vec). | |
select(&person::first_name_). | |
to_vector(); | |
// Iterate over result set | |
BOOST_FOREACH(boost::tuple<std::string> & result, out) | |
{ | |
std::cout << boost::get<0>(result) << std::endl; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment