Czy istnieje biblioteka LINQ dla C ++? [Zamknięte]

82

Czy istnieją jakieś ruchy niezależne od platformy (nie CLI), aby LINQ zaczął w jakiś sposób C ++?

Mam na myśli, że znaczna część frameworków serwerowych na całym świecie działa na odmianach UNIX, a dostęp do LINQ for C ++ w systemie UNIX prawdopodobnie uszczęśliwiłby wiele osób!

Robert Gould
źródło
1
Czy masz na myśli monadę (IEnumerable <> i zestaw metod rozszerzających na niej)? Czy masz na myśli aspekt językowy? Masz na myśli LINQ-to-SQL?
yfeldblum
Cóż, część LINQ-SQL jest częścią, której naprawdę chcę, ale to zależy od języka LINQ i monad.
Robert Gould
2
Człowieku, to naprawdę pomocne pytanie! Nie zamykaj takich pytań!
j00hi
sprawdź moją implementację github.com/DevUtilsNet/linqcpp Przeanalizowałem inne implementacje i usunąłem wszystkie wady, które mi nie odpowiadały.
antwoord

Odpowiedzi:

34

Linq ++ autorstwa Hong Jiang wygląda na dobry początek. Jego składnia jest znacznie bliższa Linq niż CLinq. Linq autorstwa pfultz2 również wygląda interesująco, ale potrzebuje kompilatora C ++ 11.

js.
źródło
1
Miły. Wersja c ++ 11 wydaje się być bardzo interesująca, nawet jeśli jego surowy przykład zrozumienia powinien był użyć Phoenix, aby uniknąć "standardowego kodu".
KitsuneYMG
hmm, nie widzę ich obsługujących bazy danych SQL.
Arne,
21

To jest moje rozwiązanie biblioteki C ++ LINQ szablonu.
Kod źródłowy jest tutaj: Boolinq
Istnieje wiele testów każdej funkcji.
Właśnie nad tym pracuję.

Jakieś uwagi?
Czy mogą być porady?

UPDATE: projekt został przeniesiony na https://github.com/k06a/boolinq i ma teraz wersję 2.0 z zaledwie 700 liniami kodu źródłowego :)

k06a
źródło
Nie mogłem używać boolinq z Qt 5.9.1 z powodu błędów kompilacji dotyczących Q_FOREACH. Prawdopodobnie z powodu Q_FOREACHwycofania.
Nikola Malešević
@ NikolaMalešević, możesz spróbować zdefiniować tuż przed dołączeniem boolinq.h: #define foreach for_eachpotem po include: #undef foreacha następnie dołączyć nagłówki Qt.
k06a
1
Naprawdę jak Boolinq! dodaj grupęBy
pingu
18

Firma Microsoft właśnie ogłosiła , że stworzyła LINQ dla C i C ++. Jednak jeszcze niedostępny.

Aktualizacja 11.06.2012:

Firma Microsoft Open Technologies, Inc. wydała i udostępniła na zasadach open source (licencja Apache 2.0) szereg powiązanych bibliotek, w tym implementację LINQ (Ix ++) i nową bibliotekę Reactive Extensions (Rx ++).

David Cuccia
źródło
8

http://cpplinq.codeplex.com/ to bardzo dobra implementacja.
Od autora:
Motywacją dla CppLinq jest to, że zarówno boolinq, jak i Native-RX wydają się być oparte na operatorze "." do tworzenia funkcji list. Problem w tym, że „.” jest taki, że nie może być przeciążony w C ++, co utrudnia rozszerzenie tych bibliotek o funkcje mojego własnego projektu. To jest dla mnie ważne. CppLinq jest oparty na operatorze >>, który jest przeciążalny, więc CppLinq można uczynić rozszerzalnym.

yufanyufan
źródło
7

Możesz rzucić okiem na PSade.Oven , mocno rozbudowaną bibliotekę pracującą na zakresach STL i udostępniającą wiele funkcji podobnych do LINQ.

zwvista
źródło
całkiem interesujące, spojrzę na to, kiedy będę miał szansę, dzięki!
Robert Gould,
7

Napisałem małą bibliotekę cppLinq, która ponownie implementuje IEnumerable <> i jej operatory LINQ. To tylko eksperyment; na razie działa tylko w systemie Windows (programy są implementowane z włóknami Win32) i buduje się tylko z wersją Dev Preview VS11 (intensywnie wykorzystuje wyrażenia lambda :-)).

Pozwala pisać taki kod:

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
źródło
7
Ślepa konwersja C # do C ++ nikomu nie pomoże. Dlaczego potrzebujesz interfejsów? Jeśli się ich pozbędziesz, pozbędziesz się wszystkich bezużytecznych alokacji, a także składni poinera. A jeśli nie możesz, przynajmniej zamień shared_ptrs na unique_ptrs, ponieważ to drugie można zamienić na pierwsze, ale nie odwrotnie. Poza tym stylowy, nie potrzebujesz -> doubletypu zwracanego. Po prostu pozwól niejawnym konwersjom wykonać swoją pracę.
Xeo,
2
Dzięki za komentarz. Tak, lambda w powyższym przykładzie można nieco poprawić, ale to tylko szczegół. Nie jestem jednak pewien, co mogę zrobić z shared_ptrs i wskaźnikami. Chodziło o to, aby zaimplementować bloki iteratorów wraz z procedurami, dokładnie tak, jak są one zaimplementowane w C #, aby zapewnić leniwe oceny i potoki danych. U źródła możemy mieć na przykład coś, co „generuje” dane z kontenera STL, ale wtedy mamy potok komponentów, który musi zachowywać się jak IEnumerators, dostarczając dane z współprogramów. Jaki interfejs miałbyś na myśli dla wersji LINQ w języku C ++?
Paolo Severini,
5
Miałem na myśli statyczne podejście oparte na szablonach wyrażeń. Przeczytaj o tym.
Xeo,
Dziękuję, Xeo, naprawdę! Szablony wyrażeń są bardzo ciekawe, na pewno spróbuję dowiedzieć się o nich więcej. Czy uważasz, że można ich użyć do zaimplementowania leniwej oceny w sensie LINQ (z sekwencjami „dawały” jeden element na raz?) Ponieważ myślę, że to jest sedno LINQ: nie chcesz modyfikować istniejących kontenerów, a ty nie chcą generować od razu wszystkich danych dla tymczasowych kontenerów, które są danymi wyjściowymi wszystkich operatorów połączonych w wyrażeniu LINQ. Musi być leniwy, w przeciwnym razie nie ma potrzeby zawracać sobie głowy LINQ, wszystko można zrobić za pomocą algorytmów stl, std i lambd.
Paolo Severini
2
Cóż… po prostu zastosuj to, co chcesz, tylko podczas dereferencji iteratora. Spójrz także na Boost.Range .
Xeo,
3

Oto inna alternatywa która jest po prostu opakowaniem algorytmów doładowania i stl, dzięki czemu uzyskujesz większość korzyści z wydajności tych implementacji.

Działa to tak:

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

Zauważ, że niektóre metody zwracają proxy dla pustych zakresów, np

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

Opinie są mile widziane.

ronag
źródło
Bardzo ładnie zrobione, podoba mi się.
Tim Sylvester
3

Właściwie, jeśli chcesz używać Linq tylko do rozumienia list, możesz użyć tej biblioteki Linq . Wymaga C ++ 11 (będzie jednak działać w MSVC 2010) i Boost. Dzięki bibliotece możesz pisać zapytania linq w następujący sposób:

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

Który wyświetli:

Omelchenko score: 97
O'Donnell score: 91
Mortensen score: 94
Garcia score: 97
Beebe score: 91
Paul Fultz II
źródło
2

C ++ 0x, lub cokolwiek zostanie wywołane, ma nowe słowo kluczowe o nazwie, autoktóre umożliwia wnioskowanie o typie. I tak, nadejdzie lambda dla C ++. Ponadto szybkie wyszukiwanie w Google ujawniło to, CLinq .

Chris
źródło
2

Oto moja implementacja c ++ - linq z c ++ 11 (po chińsku):

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

Obsługuje takie funkcje, jak „odroczone zapytanie”, „oparte na stosie” (używaj operatora new jak najmniej), „kopiuj semantyczne” (aby można było iterować zapytanie multitime po utworzeniu kopii zapasowej) i tak dalej.

Obsługuje również dziesiątki funkcji, w tym „from, select, where, cast, range, all, any, cast, Average, include, count, first, last, head, tail, groupBy, takeUntil, skipUntil, max, min, redukuj, unikalne, sortowanie, losowe, przecięcie, _union ”.

Myślę, że mój kod jest wystarczająco prosty, aby każdy mógł go zrozumieć i rozszerzyć.

Skanowanie
źródło
-4

Nie sądzę, by C ++ miał cukier kompilatora do obsługi takich rzeczy, jak wyrażenia lambda, więc nie, to się nie stanie.

FlySwat
źródło
5
C ++ 0X ma lambdę, więc teoretycznie powinno to być możliwe, ale tak, to nie jest łatwe zadanie.
Robert Gould
7
Biblioteka Boost.Phoenix dodaje również Lambdy do C ++ bez żadnych sztuczek przed kompilatorem. Zobacz tinyurl.com/d4y9se [boost.org] Oczywiście z C ++ 0x wiele tych rzeczy staje się łatwiejsze! Fajny artykuł jak zrobić LINQ z c ++ 0x tinyurl.com/d9zlsc [blogspot.com]
jk.
3
LOL, przy pomocy boost :: lambda, trochę sztuczek szablonowych iw jednym przypadku prekompilatora udało mi się wymyślić następującą składnię: from(v).where(&_1 ->* &Person::age >= 18).order_by(Person, age).top(5).order_by(Person, name)wybrać pięciu najmłodszych dorosłych ze std :: vector <Person> i zwrócić je w porządku alfabetycznym. Więc powiedziałbym, że C ++ jest wystarczające do tego zadania ...
Andreas Magnusson,
1
@ Andreas, pomyślałem, że używasz supermocy LINQ do konwersji LINQ na zapytanie SQL. W takim przypadku potrzebujesz AST i pobierz go w C #. Nie możesz tego zrobić w C ++ AFAIK.
Elazar Leibovich
1
@Elazar i @Andreas - naprawdę istnieją dwa smaki LINQ. Jeden, który działa tak, jak wydaje mi się, że Andreas działa, a drugi wykorzystuje drzewa wyrażeń (podzbiór pełnego AST), które można ponownie zinterpretować w kodzie, aby utworzyć SQL lub inną reprezentację zapytania. Aby uzyskać więcej informacji na temat tego drugiego formularza, zapoznaj się Expression<T>z dokumentacją języka C #.
Drew Noakes