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!


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.


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


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


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.


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.


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

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.


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

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 .


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ć.


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


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.