C ++でのリスト理解のためのLINQは、C ++のLINQの実装を提供します。現在、C ++範囲のみをサポートしていますが、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 ) ;
}上記のC ++コードはこれを出力します(はい、上記のC ++コードです):
Omelchenko score: 97
O'Donnell score: 91
Mortensen score: 94
Garcia score: 97
Beebe score: 91
拡張機能は、 |を使用して実装されますパイプオペレーター。これにより、特別な基本クラスから継承することなく、任意の範囲に適用できます。したがって、拡張機能は次のように機能します:
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; });サポートされている拡張メソッドは次のとおりです。
ライブラリは、独自の拡張機能を作成するためにも使用できるrange_extensionクラスも提供します。最初に関数を関数オブジェクトクラスとして定義するだけです。
struct contains_t
{
template < class Range , class T >
bool operator ()(Range && r, T && x) const
{ return (r | linq::find (x)) != boost::end (r); };
};次に、静的初期化を使用して拡張機能を初期化します。
range_extension< contains_t > contains = {};その後、拡張機能は次のように使用できます。
if (numbers | contains( 5 )) printf( " We have a 5 " );すべてのLINQクエリは、 fromステートメントから開始する必要があります。これは、ラムダに使用される変数名とクエリが適用されるコンテナを指定します。また、声明from複数を使用できます。
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 ) ) ;句は、述語に一致する要素を返します。それはオプションですが、 from句の後に来なければならず、ある場合はselect句の前にある必要があります。
vector < int > v = { 1 , 3 , 4 , 5 } ;
// { 1, 3, 5 }
auto q = LINQ ( from ( i , v ) where ( i % 2 ) ) ;Select句は、要素への変換を適用します。また、オプションですが、最後の条項である必要があります。
std :: vector < int > v = { 1 , 2 , 4 } ;
// { 3, 6, 24 }
auto q = LINQ ( from ( x , v ) select ( x * 3 ) ) ; orderby句を使用すると、範囲を注文する要素を指定できます。また、順序の方向を指定するために、 ascendingまたはdescending前にセレクターが先行することができます。デフォルトは上昇します。
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 ) ) ;group句は、シーケンスの要素をグループ化します。最初のパラメーターはキーセレクターで、2番目のパラメーターは値セレクターです。
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は、CGETで簡単にインストールできます。
cget install pfultz2/Linq
これにより、ブースト依存関係が自動的にインストールされます。ライブラリは、cmakeで手動でインストールすることもできます。
find_package(Linq) cmakeからlinqを消費するためにも利用できます。
find_package(Linq)
target_linkq_libraries(yourLib linq::linq)
完全なサポートには、ClangまたはGCCが必要です。 Visual Studioには部分的なサポートがあります。 Visual Studioは、 default_if_empty 、 group_by 、 group_join 、 join 、 order_by 、 select_many 、およびthen_by拡張機能をサポートせず、節からネストされたorderby 、 group 、およびネストされていません。おそらく、いくつかのビジュアルスタジオウィザードは、MSVCバグの回避策を見つけるのに役立つ可能性があります。
声明from複数は、ネストされたラムダを使用して実装されます。ただし、MSVC 2010のバグのため、ネストされたランバは機能しません(これはMSVC 2012で修正する必要がありますが、テストしていません)。 C ++に透明な識別子を実装する方法がある場合、ネストされたラムダは回避できます。
また、 let 、およびjoin条項はまだサポートされていません。 into句は、polymorhpic lambdasの助けなしにはサポートできません。
BSL-1.0