Чи існує бібліотека 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.
Арне

21

Це моє рішення бібліотеки шаблону C ++ LINQ.
Вихідний код тут: Boolinq
Існує безліч тестів щодо кожної функції.
Зараз я працюю над цим.

Будь-які коментарі?
Можуть бути поради?

ОНОВЛЕННЯ: проект переміщено на https://github.com/k06a/boolinq і тепер у нього версія 2.0 із лише 700 рядками вихідного коду :)


Я не міг використовувати boolinq з Qt 5.9.1 через помилки компіляції щодо Q_FOREACH. Можливо, через Q_FOREACHпоступове скасування.
Нікола Малешевич

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

1
Справді, як Boolinq! будь ласка , додайте GroupBy
Pingu


8

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


7

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


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

7

Я написав невелику бібліотеку cppLinq, яка реалізовує IEnumerable <> та його оператори LINQ. Це просто експеримент; наразі він працює лише в Windows (програми реалізовані з волокнами Win32), а збирається лише за допомогою попереднього перегляду Dev 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, оскільки останні можна перетворити на перші, але не навпаки. Крім того, стиль thingy, вам не потрібен -> doubleтип повернення. Просто нехай неявні перетворення роблять свою роботу.
Xeo

2
Дякуємо за ваш коментар. Так, лямбду у зразку вище можна було б дещо покращити, але це лише деталь. Однак я не впевнений, що я можу зробити щодо shared_ptrs та покажчиків. Ідея полягала в тому, щоб реалізувати блоки ітераторів з відповідними програмами, саме так, як вони реалізовані в C #, щоб забезпечити ліниве оцінювання та конвеєри даних. У джерелі ми можемо мати щось, що "генерує" дані із контейнера STL, наприклад, але тоді у нас є труба компонентів, яка повинна вести себе як IEnumerators, отримуючи дані із спільних підпрограм. Який інтерфейс ви б мали на увазі для версії LINQ на C ++?
Паоло Северіні

5
Я мав на увазі статичний підхід на основі шаблону виразів. Прочитайте це.
Xeo

Дякую, Ксео, справді! Шаблони виразів дуже цікаві, я обов’язково спробую дізнатися про них більше. Чи вважаєте ви, що їх можна використовувати для реалізації ледачої оцінки в сенсі LINQ (з послідовностями, що "дають" по одному елементу за раз?) Тому що, я думаю, це суть LINQ: ви не хочете змінювати існуючі контейнери, і ви не хочуть генерувати одразу всі дані для тимчасових контейнерів, які є результатом усіх операторів, об'єднаних у виразі LINQ. Це повинно бути лінивим, інакше не потрібно турбувати LINQ, ви можете робити все за допомогою stl, std алгоритмів та лямбда.
Паоло Северіні

2
Ну .. просто застосовуйте все, що завгодно, лише під час розсилання посилань ітератора. Крім того, подивіться на Boost.Range .
Xeo

4

Насправді, якщо ви просто хочете використовувати 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

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

Відгуки вітаються.


Дуже гарно зроблено, мені це подобається.
Тім Сільвестр

2

C ++ 0x або, як би там не було, його називають, має нове ключове слово з назвою, autoяке дозволяє робити висновок типу. І так, для С ++ буде лямбда. Крім того, швидкий пошук у Google виявив це, CLinq .


2

Ось моя реалізація c ++ - linq з c ++ 11 (китайською мовою):

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

Він підтримує такі функції, як "відкладений запит", "на основі стека" (використовуйте оператор new якомога менше), "copy semantic" (щоб ви могли повторити запит багаторазово після його резервного копіювання) тощо.

Він також підтримує десятки функцій, включаючи "from, select, where, cast, range, all, any, cast, середнє, містять, count, first, last, head, tail, groupBy, takeUntil, skipUntil, max, min, зменшення, унікальний, сортувати, випадковий, перетинати, _ об'єднання ".

Я думаю, що мій код досить простий для розуміння та розширення будь-ким самим.


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