LINQ für das Listenverständnis in C ++ bietet eine Implementierung von LINQ für C ++. Derzeit unterstützt es nur C ++ - Bereiche, unterstützt jedoch sowohl die Erweiterungs- als auch die Abfragemethoden für LINQ. Hier ist ein Beispiel:
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 ) ;
}Der obige C ++ - Code gibt dies aus (ja, das ist C ++ - Code oben):
Omelchenko score: 97
O'Donnell score: 91
Mortensen score: 94
Garcia score: 97
Beebe score: 91
Erweiterungen werden mit dem | implementiert Rohroperator. Auf diese Weise können sie auf einen beliebigen Bereich angewendet werden, ohne von einer speziellen Basisklasse zu verabschieden. Erweiterungen können also so funktionieren:
vector< int > numbers = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 };
auto r = numbers
| linq::where([]( int x) { return x > 2 ; })
| linq::select([]( int x) { return x * x; });Die unterstützten Erweiterungsmethoden sind:
Die Bibliothek bietet auch eine range_extension -Klasse, mit der auch Ihre eigenen Erweiterungen geschrieben werden können. Definieren Sie zuerst die Funktion als Funktionsobjektklasse wie folgt:
struct contains_t
{
template < class Range , class T >
bool operator ()(Range && r, T && x) const
{ return (r | linq::find (x)) != boost::end (r); };
};Initialisieren Sie dann die Erweiterung mithilfe der statischen Initialisierung:
range_extension< contains_t > contains = {};Dann kann die Erweiterung so verwendet werden:
if (numbers | contains( 5 )) printf( " We have a 5 " ); Alle LINQ -Abfragen müssen mit einer from ausgehen. Dies gibt den Variablennamen an, der für die Lambdas und den Container verwendet werden soll, auf den die Abfragen angewendet werden. Außerdem können mehrere from Aussagen verwendet werden.
struct student
{
std :: string name ;
std :: vector < int > grades ;
student ( ) { }
template < class Range >
student ( std :: string name , Range && r )
: name ( name ) , grades ( boost :: begin ( r ) , boost :: end ( r ) )
{ }
} ;
std :: vector < student > students =
{
student ( "Bob" , { 90 , 100 , 75 } )
student ( "Tom" , { 92 , 81 , 70 } )
student ( "Terry" , { 105 , 98 , 94 } )
} ;
// { 90, 100, 75, 92, 81, 70, 105, 98, 94 }
auto q = LINQ ( from ( s , students ) from ( g , s . grades ) select ( g ) ) ; Die WO -Klausel gibt das Element zurück, das dem Prädikat entspricht. Es ist optional, muss aber nach einer from der Klausel ausgestattete Klausel erfolgen und sollte vor einer select bestehen, wenn eine vorhanden ist.
vector < int > v = { 1 , 3 , 4 , 5 } ;
// { 1, 3, 5 }
auto q = LINQ ( from ( i , v ) where ( i % 2 ) ) ;Die Auswahlklausel wendet eine Transformation in die Elemente an. Es ist auch optional, sollte aber die allerletzte Klausel sein.
std :: vector < int > v = { 1 , 2 , 4 } ;
// { 3, 6, 24 }
auto q = LINQ ( from ( x , v ) select ( x * 3 ) ) ; Mit der orderby können Sie Elemente angeben, um den Bereich nach zu bestellen. Auch ascending oder descending kann der Selektor vorangegangen werden, um die Anweisungsrichtung anzugeben. Die Standardeinstellung steigt auf.
struct person
{
std :: string name ;
int age ;
person ( ) { }
person ( std :: string name , int age )
: name ( name ) , age ( age )
{ }
} ;
std :: vector < person > people =
{
person ( "Tom" , 25 ) ,
person ( "Bob" , 22 ) ,
person ( "Terry" , 37 ) ,
person ( "Jerry" , 22 )
}
// { "Jerry", "Bob", "Tom", "Terry" }
auto q = LINQ ( from ( p , people ) orderby ( p . age , descending p . name ) select ( p . name ) ) ; Die group gruppiert die Elemente einer Sequenz. Der erste Parameter ist der Schlüsselauswahl, und der zweite ist der Wertauswahl.
struct person
{
std :: string name ;
int age ;
person ( ) { }
person ( std :: string name , int age )
: name ( name ) , age ( age )
{ }
} ;
std :: vector < person > people =
{
person ( "Tom" , 25 ) ,
person ( "Bob" , 22 ) ,
person ( "Terry" , 37 ) ,
person ( "Jerry" , 22 )
}
auto q = LINQ ( from ( p , people ) group ( p . age , p . name ) ) ; LINQ kann einfach mit CGET installiert werden:
cget install pfultz2/Linq
Dadurch wird die Boost -Abhängigkeit automatisch installiert. Die Bibliothek kann auch manuell mit CMake installiert werden.
find_package(Linq) ist auch verfügbar, um linq von cmake zu konsumieren:
find_package(Linq)
target_linkq_libraries(yourLib linq::linq)
Für die volle Unterstützung erfordert es Clang oder GCC und steigern. Es gibt teilweise Unterstützung für Visual Studio. Visual Studio unterstützt nicht die default_if_empty , group_by , group_join , join , order_by , select_many und then_by Extensions, und es unterstützt nicht orderby , group und verschachtelt aus Klauseln. Vielleicht könnten einige Visual Studio -Zauberer helfen, Problemumgehungen für MSVC -Fehler zu finden.
Mehrfach from Erklärungen werden mit verschachtelten Lambdas implementiert. Aufgrund eines Fehlers in MSVC 2010 funktionieren verschachtelte Lambas jedoch nicht (dies sollte in MSVC 2012 behoben werden, aber ich habe es nicht getestet). Wenn es eine Möglichkeit gibt, transparente Identifikatoren in C ++ zu implementieren, könnte verschachtelte Lambdas vermieden werden.
Außerdem werden die let und join noch nicht unterstützt. Die into -Klausel kann ohne die Hilfe von polymorhpischen Lambdas nicht unterstützt werden.
BSL-1.0