I am working with filters in C++ and I would like to create a query like ODB does:
db->query (query::age > 30)
I don't know what kind of data is being passed there. I have been reading about filters in C++ (with functors, lambda expressions, ...) but it is not as simple and compact as ODB queries. In addition, these query conditions can be concatenated.
db->query_one (query::first == "Joe" && query::last == "Dirt")
I have been looking what I think that the query class code is, but I have not been able to identify how it is achieved.
I need to filter a list of instances of Systems:
class Model
{
int id;
QString name;
};
class System
{
int id;
int user_id;
Model model;
};
I would like to have something like this:
Filter<System> system_filter;
Query<System> system_query(System::id == 1 && System::Model::name == "MyModelName")
system_filter.filter(system_list, system_query);
Currently I have this code (similar to an example of the book Design Patterns in Modern C++):
template <typename T>
struct Specification
{
virtual ~Specification(){}
virtual bool is_specified(T* item) = 0;
};
template <typename T>
struct Filter
{
virtual QList<T*> filter(QList<T*> items, Specification<T>& spec)
{
QList<T*> result;
for (auto& item:items)
{
if (spec.is_specified(item))
{
result.push_back(item);
}
}
return result;
}
};
template <typename T>
struct IdSpecification: common::Specification<T>
{
int id;
IdSpecification(int id) : id(id){}
public:
bool is_specified(T* item) override
{
return item->getId() == id;
}
};
template <typename T>
struct NameSpecification: common::Specification<T>
{
QRegularExpression regex;
NameSpecification(const QRegularExpression& regex) : regex(regex){}
public:
bool is_specified(T* item) override
{
QRegularExpressionMatch match = regex.match(item->getName());
return regex.match(item->getName()).hasMatch();
}
};
template <typename T, typename B>
template <typename T>
struct AndSpecification: Specification<T>
{
Specification<T>& first;
Specification<T>& second;
AndSpecification(Specification<T>& first, Specification<T>& second): first(first), second(second){}
public:
bool is_specified(T* item) override
{
return first.is_specified(item) && second.is_specified(item);
}
};
So now I can do something like this:
IdSpecification<System> system_specification(3);
NameSpecification<System> name_specification("SytemName");
AndSpecification<System> and_specification(system_specification, type_specification);
auto system_filtered = system_filter.filter(system_list, and_specification);
Thanks!