LINQ/C++

LINQ was released as part of .NET Framework 3.5 back in 2007 – http://en.wikipedia.org/wiki/Language_Integrated_Query.

Some attempts were made to mimic its capabilities in C++, most notably the proof of concept code by Hong Jiang: https://github.com/hjiang/linqxx.

I’ve written my own, more concise version with similar functionality, which you can see below. Now I’m planning to play with specialized versions for containers with certain properties (i.e. sorted containers) so that current operations can be performed more efficiently and so that I’m able to introduce more complex operations in the future.

Comments are welcome, as I haven’t studied this subject very thoroughly. Maybe similar solutions exist and I was just unable to find them?

PS. Project Euler was reeaaaally easy this week 😉

Header

namespace linq
{
template<class SrcContainer, class Expr> class select_from_where
{
public:
	select_from_where(const SrcContainer &c, const Expr &e): m_C(c), m_Expr(e) {}

	template<class DstContainer> void into(DstContainer &d) {
		for(class SrcContainer::const_iterator it = m_C.begin(); it != m_C.end(); it++) {
			if (m_Expr(*it)) d.push_back(*it);
		}
	}

	template<class Integer> Integer count(Integer) {
		Integer res(0);
		for(class SrcContainer::const_iterator it = m_C.begin(); it != m_C.end(); it++) {
			if (m_Expr(*it)) res++;
		}
		return res;
	}
private:
	const SrcContainer &m_C;
	const Expr &m_Expr;
};

template<class SrcContainer> class select_from
{
public:
	select_from(const SrcContainer &c): m_C(c) {}
	template<class Expr> select_from_where<SrcContainer, Expr> where(const Expr &e) { return select_from_where<SrcContainer, Expr>(m_C, e); }
private:
	const SrcContainer &m_C;
};

class select
{
public:
	template<class SrcContainer> select_from<SrcContainer> from(const SrcContainer &c) { return select_from<SrcContainer>(c); }
};

Test

#include <vector>
#include <string>
#include <boost/lambda/lambda.hpp>
#include <boost/bind.hpp>
#include <iostream>

using namespace boost;

using namespace std;

struct R
{
	string a, b, c;
	int x;

	R(const string& a, const string &b, const string &c)
	{
		this->a = a;
		this->b = b;
		this->c = c;
	}

	const string& getA() const { return a; }
	const string& getB() const { return b; }
	const string& getC() const { return c; }
	const int& getX() const { return x; }
};

main()
{
	vector<R> x, y;
	x.push_back(R("Test", "Lorem", "Amet"));
	x.push_back(R("Test", "Ipsum", "Lorem"));
	x.push_back(R("Dolor", "Dolor", "Ipsum"));
	x.push_back(R("Test", "Lorem", "Adpiscin"));

	cout << (bind(&R::getA, _1) == "Test" && bind(&R::getB, _1) == "Lorem")(x[0]) << endl;
	linq::select().from(x).where(bind(&R::getA, _1) == bind(&R::getB, _1)).into(y);

	for (int i = 0; i < y.size(); i++)
	{
		cout << y[i].getA() << " " << y[i].getB() << " " << y[i].getC() << endl;
	}

	cout << linq::select().from(x).where(bind(&R::getB, _1) == "Lorem").count(1) << endl;
}

Leave a Reply

Your email address will not be published. Required fields are marked *