¿Existe una biblioteca LINQ para C ++? [cerrado]

82

¿Hay algún movimiento independiente de la plataforma (no CLI) para que LINQ funcione con C ++ de alguna manera?

Me refiero a que una gran parte de los frameworks de servidores de todo el mundo se ejecutan en versiones de UNIX y tener acceso a LINQ para C ++ en UNIX probablemente haría feliz a mucha gente.

Robert Gould
fuente
1
¿Te refieres a la mónada (IEnumerable <> y el conjunto de métodos de extensión en ella)? ¿Te refieres al aspecto del lenguaje? ¿Te refieres a LINQ-to-SQL?
yfeldblum
Bueno, la parte LINQ-SQL es la parte que realmente me gustaría, pero eso depende del lenguaje y las mónadas de LINQ.
Robert Gould
2
¡Hombre, esta es una pregunta realmente útil! ¡No cierre preguntas como estas!
j00hi
por favor revise mi implementación github.com/DevUtilsNet/linqcpp Analicé otras implementaciones y eliminé todos los defectos que no me convenían.
antwoord

Respuestas:

34

Linq ++ de Hong Jiang parece un buen comienzo. Su sintaxis es mucho más cercana a Linq que a CLinq. Linq de pfultz2 también parece interesante, pero necesita un compilador C ++ 11.

js.
fuente
1
Agradable. La versión de c ++ 11 parece muy interesante, incluso si su ejemplo de comprensión en bruto debería haber usado Phoenix para evitar el "código repetitivo".
KitsuneYMG
hmm, no los veo soportando bases de datos SQL.
Arne
21

Esta es mi solución de la biblioteca de plantilla C ++ LINQ.
El código fuente está aquí: Boolinq
Hay muchas pruebas en cada función.
Estoy trabajando en eso ahora mismo.

¿Algún comentario?
¿Pueden ser consejos?

ACTUALIZACIÓN: el proyecto se movió a https://github.com/k06a/boolinq y ahora tiene la versión 2.0 con solo 700 líneas de código fuente :)

k06a
fuente
No pude usar boolinq con Qt 5.9.1 debido a errores de compilación relacionados con Q_FOREACH. Probablemente debido a Q_FOREACHsu eliminación.
Nikola Malešević
@ NikolaMalešević puede intentar definir justo antes de incluir boolinq.h: #define foreach for_eachluego incluir: #undef foreachy luego incluir encabezados Qt.
k06a
1
¡Realmente me gusta Boolinq! por favor agregue groupBy
pingu
18

Microsoft acaba de anunciar que ha creado LINQ para C y C ++. Sin embargo, aún no está disponible.

Actualización 11/06/2012:

Microsoft Open Technologies, Inc. ha lanzado y de código abierto (Apache License 2.0) una serie de bibliotecas relacionadas, incluida una implementación LINQ (Ix ++), y su nueva biblioteca Reactive Extensions (Rx ++).

David Cuccia
fuente
8

http://cpplinq.codeplex.com/ es una muy buena implementación.
Del autor:
La motivación de CppLinq es que tanto boolinq como Native-RX parecen estar basados ​​en el operador "." para componer funciones de lista. El problema es que el "." El operador es que no se puede sobrecargar en C ++, lo que dificulta la ampliación de estas bibliotecas con funciones de mi propio diseño. Para mi esto es importante. CppLinq se basa en el operador >> que se puede sobrecargar, por lo que CppLinq se puede hacer extensible.

yufanyufan
fuente
7

Puede echar un vistazo a PSade.Oven , una biblioteca fuertemente reforzada que trabaja en rangos STL y que proporciona muchas funciones similares a LINQ.

zwvista
fuente
bastante interesante, lo echaré un vistazo cuando tenga la oportunidad, ¡gracias!
Robert Gould
7

He escrito una pequeña biblioteca cppLinq que reimplementa IEnumerable <> y sus operadores LINQ. Es solo un experimento; por ahora, solo funciona en Windows (las corrutinas se implementan con fibras Win32) y solo se compila con Dev Preview de VS11 (hace un uso intensivo de expresiones lambda :-)).

Permite escribir código como este:

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
fuente
7
La conversión ciega de C # a C ++ no le hará ningún bien a nadie. ¿Por qué necesitas las interfaces? Si se deshace de ellos, se deshace de todas esas asignaciones inútiles y también de la sintaxis de puntero. Y si no puede, al menos cambie la shared_ptrsa unique_ptrs, ya que la última se puede convertir a la primera, pero no al revés. Además, estilo cosita, no necesitas el -> doubletipo de retorno. Deja que las conversiones implícitas hagan su trabajo.
Xeo
2
Gracias por tu comentario. Sí, la lambda en el ejemplo anterior podría mejorarse un poco, pero es solo un detalle. Sin embargo, no estoy seguro de qué puedo hacer con shared_ptrs y pointers. La idea era implementar bloques de iteradores con corrutinas, exactamente como se implementan en C #, para proporcionar una evaluación perezosa y canalizaciones de datos. En la fuente podemos tener algo que "genera" datos de un contenedor STL, por ejemplo, pero luego tenemos una tubería de componentes que deben comportarse como IEnumerators, produciendo datos de co-rutinas. ¿Qué interfaz tendría en mente para una versión C ++ de LINQ?
Paolo Severini
5
Un enfoque estático basado en plantillas de expresión es lo que tenía en mente. Lee sobre eso.
Xeo
¡Gracias, Xeo, de verdad! Las plantillas de expresión son muy interesantes, definitivamente intentaré aprender más sobre ellas. ¿Crees que se pueden utilizar para implementar la evaluación diferida en el sentido de LINQ (con secuencias "producidas" un elemento a la vez?) Porque creo que esta es la esencia de LINQ: no quieres modificar los contenedores existentes, y no desea generar a la vez todos los datos para contenedores temporales que son la salida de todos los operadores concatenados en una expresión LINQ. Debe ser vago, de lo contrario no hay necesidad de molestar a LINQ, puede hacer todo con stl, algoritmos std y lambdas.
Paolo Severini
2
Bueno ... sólo aplica lo que quieras solo durante la eliminación de referencias de un iterador. Además, eche un vistazo a Boost.Range .
Xeo
3

Aquí hay otra alternativa que es simplemente una envoltura alrededor de los algoritmos boost y stl, y por lo tanto, obtiene la mayoría de los beneficios de rendimiento de esas implementaciones.

Funciona así:

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

Tenga en cuenta que algunos métodos devuelven un proxy para rangos vacíos, por ejemplo

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

Los comentarios son bienvenidos.

ronag
fuente
Muy bien hecho, me gusta.
Tim Sylvester
3

En realidad, si solo desea usar Linq para la comprensión de listas, puede usar esta biblioteca de Linq . Requiere C ++ 11 (aunque funcionará en MSVC 2010) y Boost. Con la biblioteca puede escribir consultas linq como esta:

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

Que dará como resultado:

Omelchenko score: 97
O'Donnell score: 91
Mortensen score: 94
Garcia score: 97
Beebe score: 91
Paul Fultz II
fuente
2

C ++ 0x, o como sea que termine llamándose, tiene una nueva palabra clave llamada autoque permite la inferencia de tipos. Y sí, habrá lambda para C ++. Además, una búsqueda rápida en Google reveló esto, CLinq .

Chris
fuente
2

Aquí está mi implementación de c ++ - linq con c ++ 11 (en chino):

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

Admite funciones como "consulta diferida", "basada en pila" (utilice el operador nuevo lo menos posible), "copia semántica" (para que pueda iterar una consulta varios días después de realizar una copia de seguridad), etc.

También admite docenas de funciones, entre las que se incluyen "desde, seleccionar, dónde, emitir, rango, todos, cualquiera, emitir, promedio, contener, contar, primero, último, cabeza, cola, groupBy, takeUntil, skipUntil, max, min, reducir, único, ordenado, aleatorio, intersección, unión ".

Creo que mi código es lo suficientemente simple como para que cualquiera pueda entenderlo y extenderlo.

Escanear
fuente
-4

No creo que C ++ tenga el azúcar de compilación para manejar cosas como expresiones lambda, así que no, eso no va a suceder.

FlySwat
fuente
5
C ++ 0X tiene lambda, por lo que debería ser teóricamente posible, pero sí, no es una tarea fácil.
Robert Gould
7
La biblioteca Boost.Phoenix también agrega Lambdas a C ++ sin ningún truco precompilador. Vea tinyurl.com/d4y9se [boost.org] ¡Por supuesto, con C ++ 0x muchas de estas cosas se vuelven más fáciles! Un buen artículo sobre cómo hacer LINQ con c ++ 0x tinyurl.com/d9zlsc [blogspot.com]
jk.
3
LOL, con la ayuda de boost :: lambda, algunos trucos de plantilla y en un caso determinado el precompilador, pude encontrar la siguiente sintaxis: from(v).where(&_1 ->* &Person::age >= 18).order_by(Person, age).top(5).order_by(Person, name)seleccionar a los cinco adultos más jóvenes de un std :: vector <Person> y devolverlos en orden alfabético. Entonces diría que C ++ es adecuado para la tarea ...
Andreas Magnusson
1
@Andreas, oh, pensé que estás usando los superpoderes de LINQ para convertir un LINQ en una consulta SQL. En ese caso, necesita el AST y obtenerlo con C #. No puedes hacer eso en C ++ AFAIK.
Elazar Leibovich
1
@Elazar & @Andreas: realmente hay dos sabores de LINQ. Uno que funciona como creo que lo hace Andreas, y el otro que usa árboles de expresión (un subconjunto de un AST completo) que se puede reinterpretar en código para crear SQL o alguna otra representación de consulta. Para obtener más información sobre este último formulario, busque Expression<T>en la documentación de C #.
Drew Noakes