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.