Есть ли библиотека LINQ для C ++? [закрыто]


82

Существуют ли какие-либо движения, не зависящие от платформы (не CLI), для того, чтобы каким-то образом LINQ переходил на C ++?

Я имею в виду, что большая часть серверных фреймворков по всему миру работает на разновидностях UNIX, и наличие доступа к LINQ для C ++ в UNIX, вероятно, сделает многих людей счастливыми!


1
Вы имеете в виду монаду (IEnumerable <> и набор на ней методов расширения)? Вы имеете в виду языковой аспект? Вы имеете в виду LINQ-to-SQL?
yfeldblum

Что ж, часть LINQ-SQL - это то, что мне действительно нужно, но это зависит от языка и монад LINQ.
Роберт Гулд,

2
Чувак, это действительно полезный вопрос! Пожалуйста, не закрывайте подобные вопросы!
j00hi

пожалуйста, проверьте мою имплементацию github.com/DevUtilsNet/linqcpp Я проанализировал другие реализации и удалил все недостатки, которые меня не устраивали.
antwoord

Ответы:


34

Linq ++ от Hong Jiang выглядит хорошим началом. Его синтаксис намного ближе к Linq, чем к CLinq. Linq от pfultz2 тоже выглядит интересно, но для этого нужен компилятор C ++ 11.


1
Ницца. Версия для C ++ 11 кажется очень интересной, даже если в его примере необработанного понимания следовало использовать Phoenix, чтобы избежать «шаблонного кода».
KitsuneYMG

хм, я не вижу, чтобы они поддерживали базы данных SQL.
Arne

21

Это мое решение библиотеки шаблонов C ++ LINQ.
Исходный код находится здесь: Boolinq
Для каждой функции есть много тестов.
Я работаю над этим прямо сейчас.

Любые комментарии?
Может быть советы?

ОБНОВЛЕНИЕ: проект перемещен на https://github.com/k06a/boolinq и теперь имеет версию 2.0 всего с 700 строками исходного кода :)


Я не мог использовать boolinq с Qt 5.9.1 из-за ошибок компиляции, касающихся Q_FOREACH. Вероятно, из-за Q_FOREACHпрекращения производства.
Никола Малешевич

@ NikolaMalešević, вы можете попробовать определить прямо перед include boolinq.h: #define foreach for_eachзатем после include: #undef foreachи затем включить заголовки Qt.
k06a

1
Очень нравится Boolinq! пожалуйста, добавьте группуBy
pingu

18

Microsoft только что объявила о создании LINQ для C и C ++. Однако пока недоступен.

Обновление 11.06.2012:

Microsoft Open Technologies, Inc. теперь выпустила с открытым исходным кодом (Apache License 2.0) ряд связанных библиотек, включая реализацию LINQ (Ix ++) и новую библиотеку Reactive Extensions (Rx ++).


8

http://cpplinq.codeplex.com/ - очень хорошая реализация.
От автора:
CppLinq мотивирован тем, что и boolinq, и Native-RX, похоже, основаны на операторе "." составить список функций. Проблема в том, что символ "." Оператор заключается в том, что он не может быть перегружен в C ++, что затрудняет расширение этих библиотек функциями моей собственной разработки. Для меня это важно. CppLinq основан на операторе >>, который может быть перегружен, поэтому CppLinq можно сделать расширяемым.


7

Вы можете взглянуть на PSade.Oven , сильно усовершенствованную библиотеку, работающую с диапазонами STL и предоставляющую множество функций, подобных LINQ.


довольно интересно, я посмотрю, когда у меня будет возможность, спасибо!
Роберт Гулд

7

Я написал небольшую библиотеку cppLinq, которая повторно реализует IEnumerable <> и его операторы LINQ. Это просто эксперимент; пока что он работает только в Windows (сопрограммы реализованы с помощью волокон Win32) и строится только с предварительным просмотром для разработчиков VS11 (в нем интенсивно используются лямбда-выражения :-)).

Это позволяет писать такой код:

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
Слепое преобразование C # в C ++ никому не принесет никакой пользы. Зачем нужны интерфейсы? Если вы избавитесь от них, вы избавитесь от всех этих бесполезных распределений, а также от синтаксиса указателя. И если вы не можете, по крайней мере, переключите shared_ptrs на unique_ptrs, так как последнее может быть преобразовано в первое, но не наоборот. Кроме того, style thingy, вам не нужен -> doubleвозвращаемый тип. Просто позвольте неявным преобразованиям делать свое дело.
Xeo 06

2
Спасибо за ваш комментарий. Да, лямбда в приведенном выше примере можно немного улучшить, но это всего лишь деталь. Однако я не уверен, что я могу сделать с shared_ptr и указателями. Идея заключалась в том, чтобы реализовать блоки итератора с сопрограммами, именно так, как они реализованы в C #, чтобы обеспечить ленивую оценку и конвейеры данных. В источнике у нас может быть что-то, что «генерирует» данные, например, из контейнера STL, но затем у нас есть конвейер компонентов, которые должны вести себя как IEnumerators, выдавая данные из сопрограмм. Какой интерфейс вы бы имели в виду для версии LINQ на C ++?
Паоло Северини

5
Я имел в виду статический подход, основанный на шаблонах выражений. Прочтите об этом.
Xeo

Спасибо, Xeo, правда! Шаблоны выражений очень интересны, я обязательно постараюсь узнать о них побольше. Как вы думаете, можно ли их использовать для реализации ленивых вычислений в смысле LINQ (с последовательностями, «выдававшими» по одному элементу за раз?) Потому что я думаю, что это суть LINQ: вы не хотите изменять существующие контейнеры, и вы не хотят создавать сразу все данные для временных контейнеров, которые являются выходными данными всех операторов, объединенных в выражение LINQ. Он должен быть ленивым, иначе не нужно возиться с LINQ, все можно делать с помощью алгоритмов stl, std и лямбда-выражений.
Паоло Северини

2
Ну .. просто применяйте все, что хотите, только во время разыменования итератора. Также взгляните на Boost.Range .
Xeo

3

Вот еще одна альтернатива, которая представляет собой просто оболочку для алгоритмов boost и stl, и, таким образом, вы получаете большую часть преимуществ производительности этих реализаций.

Это работает так:

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

Обратите внимание, что некоторые методы возвращают прокси для пустых диапазонов, например

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

Обратная связь приветствуется.


Очень красиво сделано, мне это нравится.
Тим Сильвестр

3

На самом деле, если вы просто хотите использовать Linq для понимания списка, вы можете использовать эту библиотеку Linq . Для этого требуется C ++ 11 (хотя он будет работать в MSVC 2010) и Boost. С помощью библиотеки вы можете писать запросы linq следующим образом:

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

Что выведет:

Omelchenko score: 97
O'Donnell score: 91
Mortensen score: 94
Garcia score: 97
Beebe score: 91

2

В C ++ 0x или чем-то еще, что он вызывает, действительно есть новое ключевое слово, autoкоторое позволяет делать вывод типа. И да, лямбда придет на C ++. Кроме того, быстрый поиск в Google показал это, CLinq .


2

Вот моя реализация c ++ - linq с c ++ 11 (на китайском языке):

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

Он поддерживает такие функции, как «отложенный запрос», «на основе стека» (как можно реже используйте оператор new), «семантическое копирование» (чтобы вы могли выполнять итерацию запроса в несколько раз после резервного копирования) и т. Д.

Он также поддерживает множество функций, включая "from, select, where, cast, range, all, any, cast, average, contain, count, first, last, head, tail, groupBy, takeUntil, skipUntil, max, min, reduce, уникальный, сортировка, случайный, пересечение, _union ".

Я думаю, что мой код достаточно прост, чтобы его мог понять и расширить кто угодно.


-4

Я не думаю, что в C ++ есть сахар компилятора для обработки таких вещей, как лямбда-выражения, поэтому нет, этого не произойдет.


5
В C ++ 0X есть лямбда, поэтому теоретически это возможно, но да, это непростая задача.
Роберт Гулд,

7
Библиотека Boost.Phoenix также добавляет Lambdas в C ++ без каких-либо уловок с предварительным компилятором. См tinyurl.com/d4y9se [boost.org] Конечно, с C ++ 0x много этого материала становится проще! Хорошая статья о том, как выполнять LINQ с помощью c ++ 0x tinyurl.com/d9zlsc [blogspot.com]
jk.

3
LOL, с помощью boost :: lambda, некоторых уловок с шаблонами и в одном конкретном случае прекомпилятора я смог придумать следующий синтаксис: from(v).where(&_1 ->* &Person::age >= 18).order_by(Person, age).top(5).order_by(Person, name)выбрать пять самых молодых взрослых из std :: vector <Person> и вернуть их в алфавитном порядке. Поэтому я бы сказал, что C ++ подходит для этой задачи ...
Андреас Магнуссон

1
@Andreas, о, я думал, что вы используете сверхспособности LINQ для преобразования LINQ в SQL-запрос. В этом случае вам понадобится AST и получите его с помощью C #. Вы не можете сделать это в C ++ AFAIK.
Элазар Лейбович

1
@Elazar & @Andreas - на самом деле существует два варианта LINQ. Один работает, как я полагаю, Андреас, а другой использует деревья выражений (подмножество полного AST), которые можно переинтерпретировать в коде для создания SQL или другого представления запроса. Дополнительную информацию о последней форме можно найти Expression<T>в документации по C #.
Дрю Ноукс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.