Gibt es eine LINQ-Bibliothek für C ++? [geschlossen]

82

Gibt es plattformunabhängige (nicht CLI) Bewegungen, um LINQ in irgendeiner Weise für C ++ zum Laufen zu bringen?

Ich meine, ein großer Teil der Server-Frameworks auf der ganzen Welt wird mit UNIX-Varianten ausgeführt, und der Zugriff auf LINQ für C ++ unter UNIX würde wahrscheinlich viele Menschen glücklich machen!

Robert Gould
quelle
1
Meinen Sie die Monade (IEnumerable <> und die darauf enthaltenen Erweiterungsmethoden)? Meinst du den sprachlichen Aspekt davon? Meinen Sie LINQ-to-SQL?
Yfeldblum
Nun, der LINQ-SQL-Teil ist der Teil, den ich wirklich möchte, aber das hängt von der Sprache und den Monaden von LINQ ab.
Robert Gould
2
Mann, das ist eine wirklich hilfreiche Frage! Bitte schließen Sie solche Fragen nicht!
J00hi
Bitte überprüfen Sie meine Implementierung github.com/DevUtilsNet/linqcpp Ich habe andere Implementierungen analysiert und alle Fehler entfernt, die nicht zu mir passten.
Antwoord

Antworten:

34

Linq ++ von Hong Jiang scheint ein guter Anfang zu sein. Die Syntax ist Linq viel näher als die von CLinq. Linq von pfultz2 sieht ebenfalls interessant aus, benötigt jedoch einen C ++ 11-Compiler.

js.
quelle
1
Nett. Die c ++ 11-Version scheint sehr interessant zu sein, auch wenn sein Beispiel für das rohe Verständnis Phoenix hätte verwenden sollen, um den "Boilerplate-Code" zu vermeiden.
KitsuneYMG
hmm ich sehe sie nicht, die SQL-Datenbanken unterstützen.
Arne
21

Dies ist meine Lösung der Vorlage C ++ LINQ Bibliothek.
Der Quellcode ist hier: Boolinq Zu
jeder Funktion gibt es viele Tests.
Ich arbeite gerade daran.

Irgendwelche Kommentare?
Kann Ratschläge sein?

UPDATE: Das Projekt wurde nach https://github.com/k06a/boolinq verschoben und hat jetzt Version 2.0 mit nur 700 Zeilen Quellcode :)

k06a
quelle
Ich konnte boolinq mit Qt 5.9.1 aufgrund von Kompilierungsfehlern nicht verwenden Q_FOREACH. Wahrscheinlich aufgrund des Q_FOREACHAuslaufens.
Nikola Malešević
@ NikolaMalešević können Sie versuchen, direkt vor include boolinq.h: #define foreach for_eachdann nach include: zu definieren #undef foreachund dann Qt-Header einzuschließen .
k06a
1
Wirklich wie Boolinq! Bitte fügen Sie groupBy
pingu
18

Microsoft hat gerade bekannt gegeben, dass sie LINQ für C und C ++ erstellt haben. Noch nicht verfügbar.

Update 11/06/2012:

Microsoft Open Technologies, Inc. hat jetzt eine Reihe verwandter Bibliotheken veröffentlicht und als Open-Source- Version (Apache License 2.0) bereitgestellt, darunter eine LINQ-Implementierung (Ix ++) und die neue Bibliothek Reactive Extensions (Rx ++).

David Cuccia
quelle
8

http://cpplinq.codeplex.com/ ist eine sehr gute Implementierung.
Vom Autor:
Die Motivation für CppLinq ist, dass sowohl Boolinq als auch Native-RX auf dem Operator "zu basieren scheinen". Listenfunktionen zusammenstellen. Das Problem ist, dass das "." Operator ist, dass es in C ++ nicht überladen werden kann, was es schwierig macht, diese Bibliotheken mit Funktionen meines eigenen Designs zu erweitern. Für mich ist das wichtig. CppLinq basiert auf dem Operator >>, der überladbar ist, sodass CppLinq erweiterbar gemacht werden kann.

Yufanyufan
quelle
7

Sie können sich PSade.Oven ansehen , eine stark verbesserte Bibliothek, die an STL-Bereichen arbeitet und viele LINQ-ähnliche Funktionen bietet.

zwvista
quelle
Sehr interessant, ich werde es mir ansehen, wenn ich die Gelegenheit dazu bekomme, danke!
Robert Gould
7

Ich habe eine kleine Bibliothek cppLinq geschrieben , die IEnumerable <> und seine LINQ-Operatoren neu implementiert. Es ist nur ein Experiment; Derzeit funktioniert es nur unter Windows (Coroutinen sind mit Win32-Fasern implementiert) und wird nur mit der Dev Preview von VS11 erstellt (Lambda-Ausdrücke werden häufig verwendet :-)).

Es erlaubt, Code wie folgt zu schreiben:

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);
});
Paolo Severini
quelle
7
Das blinde Konvertieren von C # in C ++ wird niemandem nützen. Warum brauchen Sie die Schnittstellen? Wenn Sie diese loswerden, werden Sie auch all diese nutzlosen Zuordnungen und die Zeigersyntax los. Und wenn Sie nicht können, schalten Sie zumindest das shared_ptrs auf unique_ptrs um, da das letztere in das erstere konvertiert werden kann, aber nicht umgekehrt. Außerdem benötigen Sie den -> doubleRückgabetyp nicht. Lassen Sie einfach die impliziten Konvertierungen ihren Job machen.
Xeo
2
Vielen Dank für Ihren Kommentar. Ja, das Lambda im obigen Beispiel könnte etwas verbessert werden, aber es ist nur ein Detail. Ich bin mir jedoch nicht sicher, was ich mit shared_ptrs und Zeigern tun kann. Die Idee war, Iteratorblöcke mit Coroutinen genau so zu implementieren, wie sie in C # implementiert sind, um eine verzögerte Auswertung und Daten-Pipelines bereitzustellen. An der Quelle können wir beispielsweise Daten aus einem STL-Container "generieren", aber dann haben wir eine Pipeline von Komponenten, die sich wie IEnumeratoren verhalten müssen und Daten aus Co-Routinen liefern. Welche Schnittstelle hätten Sie für eine C ++ - Version von LINQ im Sinn?
Paolo Severini
5
Ich dachte an einen statischen, auf Ausdrucksvorlagen basierenden Ansatz. Lesen Sie es nach.
Xeo
Danke, Xeo, wirklich! Ausdrucksvorlagen sind sehr interessant, ich werde auf jeden Fall versuchen, mehr über sie zu erfahren. Denken Sie, dass sie verwendet werden können, um eine verzögerte Auswertung im LINQ-Sinne zu implementieren (wobei Sequenzen jeweils ein Element "ergeben" haben?), Weil ich denke, dass dies der Kern von LINQ ist: Sie möchten vorhandene Container nicht ändern, und Sie Sie möchten nicht alle Daten für temporäre Container auf einmal generieren, die die Ausgabe aller in einem LINQ-Ausdruck verketteten Operatoren sind. Es muss faul sein, sonst muss man sich nicht um LINQ kümmern, man kann alles mit stl, std Algorithmen und Lambdas machen.
Paolo Severini
2
Nun ... wenden Sie einfach alles an, was Sie wollen, nur während der Dereferenzierung eines Iterators. Schauen Sie sich auch Boost.Range an .
Xeo
3

Hier ist eine weitere Alternative , bei der es sich lediglich um einen Wrapper für Boost- und STL-Algorithmen handelt. Auf diese Weise erhalten Sie die meisten Leistungsvorteile dieser Implementierungen.

Es funktioniert so:

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>>();

Beachten Sie, dass einige Methoden einen Proxy für leere Bereiche zurückgeben, z

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 ist willkommen.

Ronag
quelle
Sehr schön gemacht, ich mag es.
Tim Sylvester
3

Wenn Sie Linq nur zum Verständnis der Liste verwenden möchten, können Sie diese Linq- Bibliothek verwenden. Es erfordert C ++ 11 (es wird jedoch in MSVC 2010 funktionieren) und Boost. Mit der Bibliothek können Sie Linq-Abfragen wie folgt schreiben:

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);
}

Welches wird ausgegeben:

Omelchenko score: 97
O'Donnell score: 91
Mortensen score: 94
Garcia score: 97
Beebe score: 91
Paul Fultz II
quelle
2

C ++ 0x oder was auch immer es aufgerufen wird, hat ein neues Schlüsselwort, autodas Typinferenz ermöglicht. Und ja, es wird Lambda für C ++ geben. Auch eine schnelle Google- Suche ergab dies, CLinq .

Chris
quelle
2

Hier ist meine Implementierung von c ++ - linq mit c ++ 11 (auf Chinesisch):

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

Es unterstützt Funktionen wie "verzögerte Abfrage", "stapelbasiert" (verwenden Sie den neuen Operator so wenig wie möglich neu), "Semantik kopieren" (damit Sie eine Abfrage nach dem Sichern multitär iterieren können) und so weiter.

Es unterstützt auch Dutzende von Funktionen, einschließlich "von, auswählen, wo, Besetzung, Reichweite, alle, beliebig, Besetzung, Durchschnitt, enthalten, zählen, zuerst, zuletzt, Kopf, Schwanz, groupBy, takeUntil, skipUntil, max, min, reduzieren, einzigartig, sortieren, zufällig, schneiden, _union ".

Ich denke, mein Code ist einfach genug, um von jedem selbst verstanden und erweitert zu werden.

Scan
quelle
-4

Ich glaube nicht, dass C ++ den Compilerzucker hat, um Dinge wie Lambda-Ausdrücke zu verarbeiten, also nein, das wird nicht passieren.

FlySwat
quelle
5
C ++ 0X hat Lambda, also sollte es theoretisch möglich sein, aber ja, es ist keine leichte Aufgabe.
Robert Gould
7
Die Boost.Phoenix-Bibliothek fügt Lamb ++ auch Lambdas ohne Pre-Compiler-Tricks hinzu. Siehe tinyurl.com/d4y9se [boost.org] Natürlich wird mit C ++ 0x vieles einfacher! Ein schöner Artikel, wie man LINQ mit c ++ 0x tinyurl.com/d9zlsc [blogspot.com] macht
jk.
3
LOL, mit Hilfe von boost :: lambda, einigen Template-Tricks und in einem bestimmten Fall dem Precompiler konnte ich die folgende Syntax entwickeln: from(v).where(&_1 ->* &Person::age >= 18).order_by(Person, age).top(5).order_by(Person, name)die fünf jüngsten Erwachsenen aus einem std :: vector <Person> auswählen und zurückgeben in alphabetischer Reihenfolge. Also ich würde sagen, dass C ++ für die Aufgabe angemessen ist ...
Andreas Magnusson
1
@Andreas, oh, ich dachte, dass Sie die Superkräfte von LINQ verwenden, um einen LINQ in eine SQL-Abfrage umzuwandeln. In diesem Fall benötigen Sie den AST und erhalten ihn mit C #. In C ++ AFAIK ist das nicht möglich.
Elazar Leibovich
1
@Elazar & @Andreas - es gibt wirklich zwei Arten von LINQ. Einer funktioniert so, wie ich es von Andreas glaube, und der andere verwendet Ausdrucksbäume (eine Teilmenge eines vollständigen AST), die im Code neu interpretiert werden können, um SQL oder eine andere Abfragedarstellung zu erstellen. Weitere Informationen zu letzterem Formular finden Sie Expression<T>in der C # -Dokumentation.
Drew Noakes