84

Are there any Platform agnostic (not CLI) movements to get LINQ going for C++ in some fashion?

I mean a great part of server frameworks around the world run on flavors of UNIX and having access to LINQ for C++ on UNIX would probably make lots of people happy!

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
Robert Gould
  • 68,773
  • 61
  • 187
  • 272
  • 1
    Do you mean the monad (IEnumerable<> and the set of extension methods on it)? Do you mean the language aspect of it? Do you mean LINQ-to-SQL? – yfeldblum Oct 26 '08 at 04:13
  • Well the LINQ-SQL part is the part I'd really want, but that depends on LINQ's language and monads. – Robert Gould Oct 27 '08 at 02:57
  • 4
    Man, this is a really helpful question! Please do not close questions like these! – j00hi Jul 18 '19 at 13:54
  • please check my implimentation https://github.com/DevUtilsNet/linqcpp I analyzed other implementations and removed all the flaws that did not suit me. – Maxim Kapitonov Oct 25 '19 at 04:06

11 Answers11

35

Linq++ by Hong Jiang looks like a good start. Its syntax is much closer to Linq than CLinq's. Linq by pfultz2 looks interesting, as well, but it needs a C++11 compiler.

Eran
  • 423
  • 4
  • 12
js.
  • 1,787
  • 19
  • 22
25

This is my solution of template C++ LINQ library.
Source code is here: Boolinq
There are a lot of tests on each feature.
I'm working on it right now.

Any comments?
May be advices?

UPDATE: project moved to https://github.com/k06a/boolinq and now have version 2.0 with only 700 lines of source code :)

k06a
  • 17,755
  • 10
  • 70
  • 110
  • I could not use boolinq with Qt 5.9.1 due to compile errors regarding `Q_FOREACH`. Probably due to `Q_FOREACH` being phased out. – Nikola Malešević Jul 27 '17 at 20:33
  • @NikolaMalešević you can try define right before include boolinq.h: `#define foreach for_each` then after include: `#undef foreach` and then include Qt headers. – k06a Jul 28 '17 at 08:34
  • 1
    Really like Boolinq! please add groupBy – pingu Jun 25 '19 at 10:53
20

Microsoft has just announced that they've built LINQ for C and C++. Not yet available, though.

Update 11/06/2012:

Microsoft Open Technologies, Inc. has now released and open-sourced (Apache License 2.0) a number of related libraries, including a LINQ implementation (Ix++), and it's new Reactive Extensions (Rx++) library.

Update 08/15/2023:

All supported languages for Reactive Extensions, including C/C++, are now here

lightw8
  • 3,262
  • 2
  • 25
  • 35
9

http://cpplinq.codeplex.com/ is a very good implementation.
From the author:
The motivation for CppLinq is that both boolinq and Native-RX seems to be based around the operator"." to compose list functions. The problem is that the "." operator is that it can't be overloaded in C++ which makes it hard to extend these libraries with functions of my own design. To me this is important. CppLinq is based around operator>> which is overloadable thus CppLinq can be made extensible.

yufanyufan
  • 171
  • 1
  • 7
8

You may take a look at PSade.Oven, a strongly boostified library working on STL ranges and providing a lot LINQ like functions.

zwvista
  • 141
  • 2
  • 1
8

I have written a small library cppLinq that reimplements IEnumerable<> and its LINQ operators. It is just an experiment; for now it only works on Windows (coroutines are implemented with Win32 fibers), and only builds with the Dev Preview of VS11 (it makes an heavy usage of lambda expressions :-)).

It allows to write code like this:

auto source = IEnumerable<int>::Range(0, 10);

auto it = source->Where([](int val) { return ((val % 2) == 0); })
                ->Select<double>([](int val) -> double { return (val * val); }));

foreach<double>(it, [](double& val){
    printf("%.2f\n", val);
});
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 8
    Blindly convertng C# to C++ isn't going to do anybody any good. Why do you need the interfaces? If you get rid of those, you get rid of all those useless allocations and the poiner syntax too. And if you can't, atleast switch the `shared_ptr`s to `unique_ptr`s, since the latter can be converted to the former, but not vice versa. Also, style thingy, you don't need the `-> double` return type. Just let the implicit conversions do their job. – Xeo Feb 06 '12 at 13:25
  • 2
    Thanks for your comment. Yes, the lambda in the sample above could be improved a bit, but it's just a detail. I am not sure what I can do about shared_ptrs and pointers, though. The idea was to implement iterator blocks with coroutines, exactly how they are implemented in C#, in order to provide lazy evaluation and data pipelines. At the source we can have something that "generates" data from a STL container, for example, but then we have a pipe of components that must behave like IEnumerators, yielding data from co-routines. What interface would you have in mind for a C++ version of LINQ? – Paolo Severini Feb 09 '12 at 00:03
  • 5
    A static, expression template based approach is what I had in mind. [Read up on it.](http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Expression-template) – Xeo Feb 09 '12 at 00:09
  • Thank you, Xeo, really! Expression templates are very interesting, I will definitely try to learn more about them. Do you think they can be used to implement lazy evaluation in the LINQ sense (with sequences "yielded" one item at a time?) Because I think this is the gist of LINQ: you don't want to modify existing containers, and you don't want to generate at once all the data for temporary containers which are the output of all the operators concatenated in a LINQ expression. It must be lazy, otherwise there's no need to bother LINQ, you can do everything with stl, std algorithms and lambdas. – Paolo Severini Feb 09 '12 at 01:22
  • 2
    Well.. just apply whatever you want only during dereferencing of an iterator. Also, have a look at [Boost.Range](http://www.boost.org/doc/libs/1_48_0/libs/range/doc/html/index.html). – Xeo Feb 09 '12 at 02:24
6

Actually if you just want to use Linq for list comprehension, you can use this Linq library. It requires C++11(it will work in MSVC 2010 though) and Boost. With the library you can write linq queries like this:

struct student_t
{
    std::string last_name;
    std::vector<int> scores;
};

std::vector<student_t> students = 
{
    {"Omelchenko", {97, 72, 81, 60}},
    {"O'Donnell", {75, 84, 91, 39}},
    {"Mortensen", {88, 94, 65, 85}},
    {"Garcia", {97, 89, 85, 82}},
    {"Beebe", {35, 72, 91, 70}} 
};

auto scores = LINQ(from(student, students) 
                   from(score, student.scores) 
                   where(score > 90) 
                   select(std::make_pair(student.last_name, score)));

for (auto x : scores)
{
    printf("%s score: %i\n", x.first.c_str(), x.second);
}

Which will output:

Omelchenko score: 97
O'Donnell score: 91
Mortensen score: 94
Garcia score: 97
Beebe score: 91
Paul Fultz II
  • 17,682
  • 13
  • 62
  • 59
4

Here is another alternative that is simply a wrapper around boost and stl algorithms, and thus you get most of the performance benefits of those implementations.

It works like this:

std::vector<int> xs;
auto count = from(xs)
   .select([](int x){return x*x;})
   .where([](int x){return x > 16;})
   .count();
auto xs2 = from(xs)
   .select([](int x){return x*x;})
   .to<std::vector<int>>();

Note that some methods return a proxy for empty ranges, e.g.

std::vector<int> xs;
auto max = from(xs)
   .select([](int x){return x*x;})
   .where([](int x){return x > 16;})
   .max()
   .value_or(default_max_value);

Feedback is welcome.

ronag
  • 49,529
  • 25
  • 126
  • 221
3

Here is my implemention of c++-linq with c++11(in chinese):

http://www.cnblogs.com/cbscan/archive/2012/10/20/2732773.html

It support features like "deferred query","stack based"(use operator new as little as possible),"copy semantic"(so you can iterate a query multitime after backup it), and so on.

It also support dozens of function including "from, select, where, cast ,range, all, any ,cast, average ,contain, count ,first, last, head, tail ,groupBy ,takeUntil, skipUntil ,max, min ,reduce ,unique, sort, random ,intersect, _union".

I think my code is simple enough to understand and extend by anybody selves.

Sergey K.
  • 24,894
  • 13
  • 106
  • 174
Scan
  • 31
  • 2
3

C++ 0x, or whatever it ends up being called, does have a new keyword called auto which allows for type-inference. And yes, there will be lambda's coming for C++. Also, a quick Google search revealed this, CLinq.

Chris
  • 6,702
  • 8
  • 44
  • 60
-5

I don't think C++ has the compiler sugar to handle things such as lambda expressions, so no, that's not going to happen.

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
FlySwat
  • 172,459
  • 74
  • 246
  • 311
  • 5
    C++ 0X has lambda, so it should be theoretically possible, but yes it's not an easy task. – Robert Gould Oct 27 '08 at 02:55
  • Now that you mentioned that and got me thinking, another option I can imagine is to go the QT route, and use a pre-compiler to add the syntactic sugar to C++, that might be a good alternative – Robert Gould Oct 27 '08 at 02:58
  • 7
    The Boost.Phoenix Library also adds Lambdas to C++ without any pre-compiler tricks. See http://tinyurl.com/d4y9se [boost.org] Of course, with C++0x alot of this stuff becomes easier! A nice article how to do LINQ with c++0x http://tinyurl.com/d9zlsc [blogspot.com] – jk. Apr 12 '09 at 10:56
  • 3
    LOL, with the help of boost::lambda, some template trickery and in one certain case the precompiler I was able to come up with the following syntax: `from(v).where(&_1 ->* &Person::age >= 18).order_by(Person, age).top(5).order_by(Person, name)` to select the five youngest adults from a std::vector and return them in alphabetical order. So I would say that C++ is adequate for the task... – Andreas Magnusson Feb 22 '11 at 10:19
  • @Andreas, how did you get the AST of the lambda? This is the part I couldn't figure out in C++. – Elazar Leibovich Mar 07 '11 at 08:23
  • @Elazar: Uhm, now I'm confused. I don't get the AST of the lambda expression, I don't need it. `where()` simply takes a `boost::function`. As long as you use `boost::function` instead of `std::function`, `boost::lambda` fits in nicely. – Andreas Magnusson Mar 07 '11 at 15:51
  • 1
    @Andreas, oh I thought that you're using LINQ's superpowers to convert a LINQ to an SQL query. In that case you need the AST and get it with C#. You can't do that in C++ AFAIK. – Elazar Leibovich Mar 07 '11 at 16:29
  • 1
    @Elazar & @Andreas -- there are really two flavours of LINQ. One that operates as I believe Andreas's does, and the other that uses expression trees (a subset of a full AST) that can be reinterpreted in code to create SQL or some other query representation. For more information on the latter form, look up `Expression` in the C# documentation. – Drew Noakes Jun 28 '11 at 20:55
  • 1
    Your answer is clearly wrong. I suggest you remove it. – Keith Pinson Mar 15 '14 at 02:36