├── Test ├── compile_with_mingw.bat ├── compile_with_mingw.sh ├── CppLinq.micro.cpp ├── CppLinq2010Express.cpp ├── compile_with_g++.sh ├── compile_with_clang++.sh ├── TODO.txt ├── stdafx.cpp ├── stdafx.h ├── CppLinq2010Express.vcxproj ├── CppLinq.cpp ├── CppLinq2012.vcxproj ├── CppLinq2013.vcxproj └── CppLinqTests.hpp ├── Media ├── cpplinq.png ├── cpplinqi.png └── icon.xaml ├── CppLinq.Mini ├── compile_with_g++.sh ├── compile_with_mingw.bat ├── compile_with_clang++.sh ├── stdafx.cpp ├── CppLinq.Mini.cpp ├── stdafx.h ├── CppLinq2012.Mini.vcxproj └── CppLinq2013.Mini.vcxproj ├── CppLinq2013.UnitTest ├── stdafx.h ├── stdafx.cpp ├── CppLinqTest.cpp ├── CppLinq2013.UnitTest.vcxproj.filters ├── CodeCoverage.runsettings └── CppLinq2013.UnitTest.vcxproj ├── .gitignore ├── README.md ├── CppLinq2010Express.sln ├── NuGet └── cpplinq.autopkg ├── CppLinq2012.sln ├── CppLinq2013.sln ├── License.html └── docs └── cpplinq-info.txt /Test/compile_with_mingw.bat: -------------------------------------------------------------------------------- 1 | g++ -std=c++0x -O2 -Wall CppLinq.cpp -o cpplinq.exe -------------------------------------------------------------------------------- /Test/compile_with_mingw.sh: -------------------------------------------------------------------------------- 1 | g++ -std=c++0x -O2 -Wall CppLinq.cpp -o cpplinq.exe -------------------------------------------------------------------------------- /Media/cpplinq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrange/cpplinq/HEAD/Media/cpplinq.png -------------------------------------------------------------------------------- /Media/cpplinqi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrange/cpplinq/HEAD/Media/cpplinqi.png -------------------------------------------------------------------------------- /CppLinq.Mini/compile_with_g++.sh: -------------------------------------------------------------------------------- 1 | g++ -std=c++0x -O2 -Wall CppLinq.Mini.cpp -o cpplinqmini 2 | -------------------------------------------------------------------------------- /CppLinq.Mini/compile_with_mingw.bat: -------------------------------------------------------------------------------- 1 | g++ -std=c++0x -O2 -Wall CppLinq.Mini.cpp -o cpplinqmini.exe -------------------------------------------------------------------------------- /Test/CppLinq.micro.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrange/cpplinq/HEAD/Test/CppLinq.micro.cpp -------------------------------------------------------------------------------- /CppLinq.Mini/compile_with_clang++.sh: -------------------------------------------------------------------------------- 1 | clang++ -std=c++0x -O2 -Wall CppLinq.Mini.cpp -o cpplinqmini 2 | -------------------------------------------------------------------------------- /CppLinq2013.UnitTest/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrange/cpplinq/HEAD/CppLinq2013.UnitTest/stdafx.h -------------------------------------------------------------------------------- /Test/CppLinq2010Express.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrange/cpplinq/HEAD/Test/CppLinq2010Express.cpp -------------------------------------------------------------------------------- /CppLinq2013.UnitTest/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrange/cpplinq/HEAD/CppLinq2013.UnitTest/stdafx.cpp -------------------------------------------------------------------------------- /CppLinq2013.UnitTest/CppLinqTest.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrange/cpplinq/HEAD/CppLinq2013.UnitTest/CppLinqTest.cpp -------------------------------------------------------------------------------- /Test/compile_with_g++.sh: -------------------------------------------------------------------------------- 1 | g++ -std=c++11 -O2 -Wall -Wformat=2 -Wformat-security -Wpedantic CppLinq.cpp -o cpplinq.g++ 2 | -------------------------------------------------------------------------------- /Test/compile_with_clang++.sh: -------------------------------------------------------------------------------- 1 | clang++ -std=c++11 -O2 -Wall -Wformat=2 -Wformat-security -Wpedantic CppLinq.cpp -o cpplinq.clang++ 2 | -------------------------------------------------------------------------------- /Test/TODO.txt: -------------------------------------------------------------------------------- 1 | NEXT:25 2 | 4. to_map should accept a value selector predicate 3 | 22. Do we use cleanup_type overzeolously? It adds performance impact going value_type when reference type would work 4 | 7. Fix container range aggregator iterator semantics 5 | 9. Document container range aggregator 6 | 14. Performance test for classes that are expensive to copy 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # git ls-files --others --exclude-from=.git/info/exclude 2 | # Lines that start with '#' are comments. 3 | # For a project mostly in C, the following would be a good set of 4 | # exclude patterns (uncomment them if you want to use them): 5 | # *.[oa] 6 | # *~ 7 | *.sdf 8 | *.opensdf 9 | *.suo 10 | *.exe 11 | *.dll 12 | *.user 13 | ut.txt 14 | *.nupkg 15 | Output/ 16 | CppLinq/Intermediate/ 17 | CppLinq.Mini/Intermediate/ 18 | Test/Intermediate/ 19 | CppLinq/Intermediate2013/ 20 | CppLinq.Mini/Intermediate2013/ 21 | Test/Intermediate2013/ 22 | CppLinq2013.UnitTest/Intermediate2013/ 23 | ipch/ 24 | _Resharper.CppLinq/ 25 | Test/cpplinq.* 26 | TestResults/ 27 | 28 | -------------------------------------------------------------------------------- /CppLinq2013.UnitTest/CppLinq2013.UnitTest.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | cpplinq - LINQ-like list manipulations for C++11 2 | ================================================ 3 | 4 | LINQ for C++ (cpplinq) is an extensible C++11 library of higher-order functions for range manipulation. cpplinq draws inspiration from LINQ for C#. 5 | 6 | ```cpp 7 | #include "cpplinq.hpp" 8 | 9 | int computes_a_sum () 10 | { 11 | using namespace cpplinq; 12 | int ints[] = {3,1,4,1,5,9,2,6,5,4}; 13 | 14 | // Computes the sum of all even numbers in the sequence above 15 | return 16 | from_array (ints) 17 | >> where ([](int i) {return i%2 ==0;}) // Keep only even numbers 18 | >> sum () // Sum remaining numbers 19 | ; 20 | } 21 | ``` 22 | 23 | See the documentation: http://cpplinq.codeplex.com/documentation 24 | 25 | 26 | -------------------------------------------------------------------------------- /CppLinq2010Express.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppLinq2010Express", "Test\CppLinq2010Express.vcxproj", "{F1095606-99A2-4DCF-B357-5A14115482D4}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {F1095606-99A2-4DCF-B357-5A14115482D4}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {F1095606-99A2-4DCF-B357-5A14115482D4}.Debug|Win32.Build.0 = Debug|Win32 14 | {F1095606-99A2-4DCF-B357-5A14115482D4}.Release|Win32.ActiveCfg = Release|Win32 15 | {F1095606-99A2-4DCF-B357-5A14115482D4}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /Media/icon.xaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Test/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------------------- 2 | // Copyright (c) Mårten Rånge. 3 | // ---------------------------------------------------------------------------------------------- 4 | // This source code is subject to terms and conditions of the Microsoft Public License. A 5 | // copy of the license can be found in the License.html file at the root of this distribution. 6 | // If you cannot locate the Microsoft Public License, please send an email to 7 | // dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 8 | // by the terms of the Microsoft Public License. 9 | // ---------------------------------------------------------------------------------------------- 10 | // You must not remove this notice, or any other, from this software. 11 | // ---------------------------------------------------------------------------------------------- 12 | #include "stdafx.h" 13 | // ---------------------------------------------------------------------------------------------- 14 | -------------------------------------------------------------------------------- /CppLinq.Mini/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------------------- 2 | // Copyright (c) Mårten Rånge. 3 | // ---------------------------------------------------------------------------------------------- 4 | // This source code is subject to terms and conditions of the Microsoft Public License. A 5 | // copy of the license can be found in the License.html file at the root of this distribution. 6 | // If you cannot locate the Microsoft Public License, please send an email to 7 | // dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 8 | // by the terms of the Microsoft Public License. 9 | // ---------------------------------------------------------------------------------------------- 10 | // You must not remove this notice, or any other, from this software. 11 | // ---------------------------------------------------------------------------------------------- 12 | #include "stdafx.h" 13 | // ---------------------------------------------------------------------------------------------- 14 | -------------------------------------------------------------------------------- /NuGet/cpplinq.autopkg: -------------------------------------------------------------------------------- 1 | nuget{ 2 | nuspec{ 3 | id = cpplinq; 4 | version : 2013.08.10; 5 | title: cpplinq; 6 | authors: {Mårten Rånge, Marius Bancila, d95danb}; 7 | owners: {cpplinq, Mårten Rånge, Marius Bancila}; 8 | licenseUrl: "http://cpplinq.codeplex.com/license"; 9 | projectUrl: "http://cpplinq.codeplex.com/"; 10 | iconUrl: "https://raw.github.com/mrange/cpplinq/master/Media/cpplinqi.png" 11 | requireLicenseAcceptance:false; 12 | summary:"cpplinq is an open-source native template library that provides a set of LINQ-like operators for querying collections (arrays and STL containers) in C++11."; 13 | description:@"cpplinq is an open-source native template library that provides a set of LINQ-like operators for querying collections (arrays and STL containers) in C++11. 14 | 15 | The library contains a single header file and the API consists on a set of template classes and functions and is compatible with all major compilers (VC++, mingw, g++, clang++)."; 16 | releaseNotes:February 2013 stable release (updates only in the NuGet package).; 17 | copyright: Copyright 2013; 18 | tags: { native, C++, LINQ, cpplinq, query }; 19 | } 20 | 21 | files { 22 | #defines { 23 | CPPLINQ_BASE = ..\; 24 | } 25 | 26 | include += { ${CPPLINQ_BASE}cpplinq\cpplinq.hpp }; 27 | 28 | docs += { ${CPPLINQ_BASE}docs\cpplinq-info.txt }; 29 | } 30 | props { 31 | Defines += NOMINMAX; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CppLinq.Mini/CppLinq.Mini.cpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------------------- 2 | // Copyright (c) Mårten Rånge. 3 | // ---------------------------------------------------------------------------------------------- 4 | // This source code is subject to terms and conditions of the Microsoft Public License. A 5 | // copy of the license can be found in the License.html file at the root of this distribution. 6 | // If you cannot locate the Microsoft Public License, please send an email to 7 | // dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 8 | // by the terms of the Microsoft Public License. 9 | // ---------------------------------------------------------------------------------------------- 10 | // You must not remove this notice, or any other, from this software. 11 | // ---------------------------------------------------------------------------------------------- 12 | #include "stdafx.h" 13 | // ---------------------------------------------------------------------------------------------- 14 | #include "../CppLinq/cpplinq.hpp" 15 | // ---------------------------------------------------------------------------------------------- 16 | int main (int argc, char* args[]) 17 | { 18 | using namespace cpplinq; 19 | auto begin = args; 20 | auto end = args + argc; 21 | 22 | auto result = from_iterators (begin, end) 23 | >> skip (1) 24 | >> select ([] (char * cs) {return strlen (cs);}) 25 | >> sum () 26 | ; 27 | 28 | printf ("%d\n", result); 29 | 30 | return 0; 31 | } 32 | // ---------------------------------------------------------------------------------------------- 33 | -------------------------------------------------------------------------------- /CppLinq.Mini/stdafx.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------------------- 2 | // Copyright (c) Mårten Rånge. 3 | // ---------------------------------------------------------------------------------------------- 4 | // This source code is subject to terms and conditions of the Microsoft Public License. A 5 | // copy of the license can be found in the License.html file at the root of this distribution. 6 | // If you cannot locate the Microsoft Public License, please send an email to 7 | // dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 8 | // by the terms of the Microsoft Public License. 9 | // ---------------------------------------------------------------------------------------------- 10 | // You must not remove this notice, or any other, from this software. 11 | // ---------------------------------------------------------------------------------------------- 12 | #ifndef HEADER_GUARD__STDAFX 13 | # define HEADER_GUARD__STDAFX 14 | // ---------------------------------------------------------------------------------------------- 15 | #include 16 | #include 17 | // ---------------------------------------------------------------------------------------------- 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | // ---------------------------------------------------------------------------------------------- 32 | #endif // HEADER_GUARD__STDAFX 33 | // ---------------------------------------------------------------------------------------------- 34 | -------------------------------------------------------------------------------- /CppLinq2012.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppLinq", "Test\CppLinq2012.vcxproj", "{B2C5078E-E859-4BF8-A799-75653FE524AB}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppLinq.Mini", "CppLinq.Mini\CppLinq2012.Mini.vcxproj", "{4CE7EBDE-D1A2-4B5D-853C-921668821E50}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|Win32.Build.0 = Debug|Win32 18 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|x64.ActiveCfg = Debug|x64 19 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|x64.Build.0 = Debug|x64 20 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|Win32.ActiveCfg = Release|Win32 21 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|Win32.Build.0 = Release|Win32 22 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|x64.ActiveCfg = Release|x64 23 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|x64.Build.0 = Release|x64 24 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|Win32.Build.0 = Debug|Win32 26 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|x64.ActiveCfg = Debug|Win32 27 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|Win32.ActiveCfg = Release|Win32 28 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|Win32.Build.0 = Release|Win32 29 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|x64.ActiveCfg = Release|x64 30 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|x64.Build.0 = Release|x64 31 | EndGlobalSection 32 | GlobalSection(SolutionProperties) = preSolution 33 | HideSolutionNode = FALSE 34 | EndGlobalSection 35 | EndGlobal 36 | -------------------------------------------------------------------------------- /Test/stdafx.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------------------- 2 | // Copyright (c) Mårten Rånge. 3 | // ---------------------------------------------------------------------------------------------- 4 | // This source code is subject to terms and conditions of the Microsoft Public License. A 5 | // copy of the license can be found in the License.html file at the root of this distribution. 6 | // If you cannot locate the Microsoft Public License, please send an email to 7 | // dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 8 | // by the terms of the Microsoft Public License. 9 | // ---------------------------------------------------------------------------------------------- 10 | // You must not remove this notice, or any other, from this software. 11 | // ---------------------------------------------------------------------------------------------- 12 | #ifndef HEADER_GUARD__STDAFX 13 | # define HEADER_GUARD__STDAFX 14 | // ---------------------------------------------------------------------------------------------- 15 | #ifdef _MSC_VER 16 | # define NOMINMAX 17 | #endif 18 | // ---------------------------------------------------------------------------------------------- 19 | #ifdef _MSC_VER 20 | # include 21 | #endif 22 | // ---------------------------------------------------------------------------------------------- 23 | #include 24 | // ---------------------------------------------------------------------------------------------- 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | // ---------------------------------------------------------------------------------------------- 39 | #endif // HEADER_GUARD__STDAFX 40 | // ---------------------------------------------------------------------------------------------- 41 | -------------------------------------------------------------------------------- /CppLinq2013.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30110.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppLinq2013", "Test\CppLinq2013.vcxproj", "{B2C5078E-E859-4BF8-A799-75653FE524AB}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppLinq2013.Mini", "CppLinq.Mini\CppLinq2013.Mini.vcxproj", "{4CE7EBDE-D1A2-4B5D-853C-921668821E50}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4203A08B-EAD5-4C1C-98AA-508D6A74CEAC}" 11 | ProjectSection(SolutionItems) = preProject 12 | .gitignore = .gitignore 13 | EndProjectSection 14 | EndProject 15 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppLinq2013.UnitTest", "CppLinq2013.UnitTest\CppLinq2013.UnitTest.vcxproj", "{081E2554-9A17-45E3-9264-DC677FCE8DA2}" 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Win32 = Debug|Win32 20 | Debug|x64 = Debug|x64 21 | Release|Win32 = Release|Win32 22 | Release|x64 = Release|x64 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|Win32.ActiveCfg = Debug|Win32 26 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|Win32.Build.0 = Debug|Win32 27 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|x64.ActiveCfg = Debug|x64 28 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|x64.Build.0 = Debug|x64 29 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|Win32.ActiveCfg = Release|Win32 30 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|Win32.Build.0 = Release|Win32 31 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|x64.ActiveCfg = Release|x64 32 | {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|x64.Build.0 = Release|x64 33 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|Win32.ActiveCfg = Debug|Win32 34 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|Win32.Build.0 = Debug|Win32 35 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|x64.ActiveCfg = Debug|x64 36 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|x64.Build.0 = Debug|x64 37 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|Win32.ActiveCfg = Release|Win32 38 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|Win32.Build.0 = Release|Win32 39 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|x64.ActiveCfg = Release|x64 40 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|x64.Build.0 = Release|x64 41 | {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Debug|Win32.ActiveCfg = Debug|Win32 42 | {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Debug|Win32.Build.0 = Debug|Win32 43 | {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Debug|x64.ActiveCfg = Debug|x64 44 | {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Debug|x64.Build.0 = Debug|x64 45 | {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Release|Win32.ActiveCfg = Release|Win32 46 | {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Release|Win32.Build.0 = Release|Win32 47 | {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Release|x64.ActiveCfg = Release|x64 48 | {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Release|x64.Build.0 = Release|x64 49 | EndGlobalSection 50 | GlobalSection(SolutionProperties) = preSolution 51 | HideSolutionNode = FALSE 52 | EndGlobalSection 53 | EndGlobal 54 | -------------------------------------------------------------------------------- /License.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 | 10 | 11 | 75 | 76 |
12 |

13 | Microsoft Public License (Ms-PL) 14 |

15 |

16 | This license governs use of the accompanying software. If you use the software, 17 | you accept this license. If you do not accept the license, do not use the software.

18 |

19 | 1. Definitions 20 |

21 |

22 | The terms "reproduce," "reproduction," "derivative works," 23 | and "distribution" have the same meaning here as under U.S. copyright 24 | law. A "contribution" is the original software, or any additions or changes 25 | to the software. A "contributor" is any person that distributes its contribution 26 | under this license. "Licensed patents" are a contributor's patent claims 27 | that read directly on its contribution.

28 |

29 | 2. Grant of Rights 30 |

31 |

32 | (A) Copyright Grant- Subject to the terms of this license, including the license 33 | conditions and limitations in section 3, each contributor grants you a non-exclusive, 34 | worldwide, royalty-free copyright license to reproduce its contribution, prepare 35 | derivative works of its contribution, and distribute its contribution or any derivative 36 | works that you create. 37 |

38 |

39 | (B) Patent Grant- Subject to the terms of this license, including the license conditions 40 | and limitations in section 3, each contributor grants you a non-exclusive, worldwide, 41 | royalty-free license under its licensed patents to make, have made, use, sell, offer 42 | for sale, import, and/or otherwise dispose of its contribution in the software or 43 | derivative works of the contribution in the software. 44 |

45 |

46 | 3. Conditions and Limitations 47 |

48 |

49 | (A) No Trademark License- This license does not grant you rights to use any contributors' 50 | name, logo, or trademarks. 51 |

52 |

53 | (B) If you bring a patent claim against any contributor over patents that you claim 54 | are infringed by the software, your patent license from such contributor to the 55 | software ends automatically. 56 |

57 |

58 | (C) If you distribute any portion of the software, you must retain all copyright, 59 | patent, trademark, and attribution notices that are present in the software. 60 |

61 |

62 | (D) If you distribute any portion of the software in source code form, you may do 63 | so only under this license by including a complete copy of this license with your 64 | distribution. If you distribute any portion of the software in compiled or object 65 | code form, you may only do so under a license that complies with this license. 66 |

67 |

68 | (E) The software is licensed "as-is." You bear the risk of using it. The 69 | contributors give no express warranties, guarantees or conditions. You may have 70 | additional consumer rights under your local laws which this license cannot change. 71 | To the extent permitted under your local laws, the contributors exclude the implied 72 | warranties of merchantability, fitness for a particular purpose and non-infringement. 73 |

74 |
77 | 78 | 79 | -------------------------------------------------------------------------------- /Test/CppLinq2010Express.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | Create 17 | 18 | 19 | 20 | 21 | 22 | 23 | {F1095606-99A2-4DCF-B357-5A14115482D4} 24 | Win32Proj 25 | CppLinq2010Express 26 | 27 | 28 | 29 | Application 30 | true 31 | Unicode 32 | 33 | 34 | Application 35 | false 36 | true 37 | Unicode 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | true 51 | 52 | 53 | false 54 | 55 | 56 | 57 | Use 58 | Level3 59 | Disabled 60 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 61 | 62 | 63 | Console 64 | true 65 | 66 | 67 | 68 | 69 | Level3 70 | Use 71 | MaxSpeed 72 | true 73 | true 74 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 75 | 76 | 77 | Console 78 | true 79 | true 80 | true 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /docs/cpplinq-info.txt: -------------------------------------------------------------------------------- 1 | == DESCRIPTION == 2 | cpplinq is an open-source native template library that provides a set of LINQ-like operators for querying collections (arrays and STL containers) in C++11. 3 | 4 | The library contains a single header file and the API consists on a set of template classes and functions and is compatible with all major compilers. 5 | 6 | == WEBSITE == 7 | http://cpplinq.codeplex.com/ 8 | 9 | == SUPPORTED COMPILERS == 10 | Windows 11 | VC++ (2010, 2012, 2013) 12 | mingw (g++ v4.7.0) 13 | 14 | Linux 15 | g++ (v4.7.0) 16 | clang++ (v3.1) 17 | 18 | == DOCUMENTATION == 19 | LINQ for C++ - getting started 20 | http://cpplinq.codeplex.com/wikipage?title=LINQ%20for%20C%2b%2b%20-%20getting%20started&referringTitle=Documentation 21 | An introduction to cpplinq, with samples and other considerations. 22 | 23 | cpplinq supported compilers 24 | http://cpplinq.codeplex.com/wikipage?title=cpplinq%20supported%20compilers&referringTitle=Documentation 25 | Lists the supported compilers for the library. 26 | 27 | Cpplinq Query Operators 28 | http://cpplinq.codeplex.com/wikipage?title=Cpplinq%20Query%20Operators&referringTitle=Documentation 29 | Documents all the available cpplinq APIs with examples. 30 | 31 | Comparison to the .NET Standard Query Operators 32 | http://cpplinq.codeplex.com/wikipage?title=Comparison%20to%20the%20.NET%20Standard%20Query%20Operators&referringTitle=Documentation 33 | Shows a comparison between the .NET standard query operators and the cpplinq operators. 34 | 35 | Advanced usages of CppLinq 36 | http://cpplinq.codeplex.com/wikipage?title=Advanced%20usages%20of%20CppLinq&referringTitle=Documentation 37 | Explains how to extend the library API with new operators. 38 | 39 | cpplinq - LINQ Query Operators for C++ Sequences 40 | http://www.codeproject.com/Articles/488177/cpplinq-LINQ-Query-Operators-for-Cplusplus-Sequenc 41 | 42 | == HOW TO USE == 43 | 1. Download the latest version of the source code from here (it's small): http://cpplinq.codeplex.com/downloads/get/616650 44 | 2. Add the header file to your C++ project 45 | 3. Include the header in the source files were you want to use the query operators (which are defined in the cpplinq namespace) 46 | 4. In VC++, you have to define NOMINMAX in order to avoid including the min/max macros. If you use NuGet, this is automatically defined. 47 | 48 | == EXAMPLES == 49 | The following example shows how to compute the sum of the even numbers from an array. 50 | 51 | #include "cpplinq.hpp" 52 | 53 | void computes_a_sum () 54 | { 55 | using namespace cpplinq; 56 | int ints[] = {3,1,4,1,5,9,2,6,5,4}; 57 | 58 | auto result = from_array (ints) 59 | >> where ([](int i) {return i%2 ==0;}) // Keep only even numbers 60 | >> sum () // Sum remaining numbers 61 | ; 62 | } 63 | 64 | The next sample shows how to identify the distinct elements of a sequence. 65 | 66 | int ints[] = {3,1,4,1,5,9,2,6,5,4}; 67 | auto result = from_array(ints) 68 | >> distinct() // identify distinct elements 69 | >> to_vector() // fold the result to a vector 70 | ; 71 | 72 | Given the customer and customer_address types shown bellow and the arrays with customers and addresses in this listing 73 | 74 | struct customer 75 | { 76 | std::size_t id ; 77 | std::string first_name ; 78 | std::string last_name ; 79 | }; 80 | 81 | struct customer_address 82 | { 83 | std::size_t id ; 84 | std::size_t customer_id ; 85 | std::string country ; 86 | }; 87 | 88 | customer customers[] = 89 | { 90 | customer (1 , "Bill" , "Gates" ), 91 | customer (2 , "Steve" , "Jobs" ), 92 | customer (3 , "Richard" , "Stallman"), 93 | customer (4 , "Linus" , "Torvalds"), 94 | }; 95 | 96 | customer_address customer_addresses[] = 97 | { 98 | customer_address (1, 1, "USA" ), 99 | customer_address (2, 4, "Finland" ), 100 | customer_address (3, 4, "USA" ), 101 | }; 102 | 103 | we can join them with the following piece of code: 104 | 105 | auto result = 106 | from_array(customers) 107 | >> join ( 108 | from_array(customer_addresses), 109 | [](customer const & c) {return c.id;}, 110 | [](customer_address const & ca) {return ca.customer_id;}, 111 | [](customer const & c, customer_address const & ca) {return std::make_pair (c, ca);}, 112 | ) 113 | >> to_vector(); -------------------------------------------------------------------------------- /Test/CppLinq.cpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------------------- 2 | // Copyright (c) Mårten Rånge. 3 | // ---------------------------------------------------------------------------------------------- 4 | // This source code is subject to terms and conditions of the Microsoft Public License. A 5 | // copy of the license can be found in the License.html file at the root of this distribution. 6 | // If you cannot locate the Microsoft Public License, please send an email to 7 | // dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 8 | // by the terms of the Microsoft Public License. 9 | // ---------------------------------------------------------------------------------------------- 10 | // You must not remove this notice, or any other, from this software. 11 | // ---------------------------------------------------------------------------------------------- 12 | #include "stdafx.h" 13 | // ---------------------------------------------------------------------------------------------- 14 | #include "CppLinqTests.hpp" 15 | // ---------------------------------------------------------------------------------------------- 16 | int main (int argc, char const * argv[]) 17 | { 18 | printf ( 19 | "CppLinq test program\n" 20 | "====================\n" 21 | "Command line options:\n" 22 | "f - run functional tests (default)\n" 23 | #ifndef _DEBUG 24 | "p - run functional + performance tests\n" 25 | #endif 26 | #ifdef _MSC_VER 27 | # ifdef _DEBUG 28 | "m - run memory leak detection test\n" 29 | # endif 30 | #endif 31 | ); 32 | 33 | auto opt = argc < 2 ? 'f' : argv[1][0]; 34 | 35 | auto failures_detected = false; 36 | 37 | switch (opt) 38 | { 39 | #ifdef _MSC_VER 40 | # ifdef _DEBUG 41 | case 'm': 42 | { 43 | printf ("Starting memory leak detection test...\n"); 44 | 45 | _CrtMemState before; 46 | _CrtMemState after; 47 | _CrtMemState diff; 48 | 49 | _CrtMemCheckpoint (&before); 50 | 51 | run_all_tests (false); 52 | 53 | _CrtMemCheckpoint (&after); 54 | if (_CrtMemDifference(&diff, &before, &after)) 55 | { 56 | auto reporter = [] (int nRptType, char *szMsg, int *retVal) 57 | { 58 | *retVal = 0; 59 | 60 | char const * rptType = "UNKNOWN"; 61 | switch (nRptType) 62 | { 63 | case _CRT_WARN: 64 | rptType = "WARNING"; 65 | break; 66 | case _CRT_ERROR: 67 | rptType = "ERROR "; 68 | break; 69 | case _CRT_ASSERT: 70 | rptType = "ASSERT "; 71 | break; 72 | default: 73 | break; 74 | } 75 | 76 | printf ( 77 | "%s - %s" 78 | , rptType 79 | , szMsg 80 | ); 81 | return 0; 82 | }; 83 | _CrtSetReportHook (reporter); 84 | 85 | _CrtMemDumpStatistics (&diff); 86 | 87 | printf ("Dumping leaked objects...\n"); 88 | 89 | _CrtDumpMemoryLeaks (); 90 | 91 | printf ( 92 | "Objects dumped\n" 93 | "Note: Some leaks are expected due to CRT allocatations\n" 94 | ); 95 | 96 | _CrtSetReportHook (nullptr); 97 | 98 | failures_detected = true; 99 | } 100 | else 101 | { 102 | failures_detected = false; 103 | } 104 | 105 | printf ("Memory leak detection finished\n"); 106 | } 107 | break; 108 | # endif 109 | #endif 110 | #ifndef _DEBUG 111 | case 'p': 112 | printf ("Starting functional + performance tests...\n"); 113 | 114 | failures_detected = run_all_tests (true); 115 | 116 | printf ("Functional + performance tests finished\n"); 117 | break; 118 | #endif 119 | case 'f': 120 | default: 121 | printf ("Starting functional tests...\n"); 122 | 123 | failures_detected = run_all_tests (false); 124 | 125 | printf ("Functional tests finished\n"); 126 | break; 127 | } 128 | 129 | if (failures_detected) 130 | { 131 | printf ("Tests failed, reporting 101\n"); 132 | return 101; 133 | } 134 | else 135 | { 136 | printf ("Tests succeeded, reporting 0\n"); 137 | return 0; 138 | } 139 | } 140 | // ---------------------------------------------------------------------------- - 141 | 142 | -------------------------------------------------------------------------------- /CppLinq2013.UnitTest/CodeCoverage.runsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | .*\.dll$ 33 | .*\.exe$ 34 | 35 | 36 | .*CPPUnitTestFramework.* 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ^Fabrikam\.UnitTest\..* 45 | ^std::.* 46 | ^ATL::.* 47 | .*::__GetTestMethodInfo.* 48 | ^Microsoft::VisualStudio::CppCodeCoverageFramework::.* 49 | ^Microsoft::VisualStudio::CppUnitTestFramework::.* 50 | ^cpplinq::.*::what$ 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | ^System.Diagnostics.DebuggerHiddenAttribute$ 59 | ^System.Diagnostics.DebuggerNonUserCodeAttribute$ 60 | ^System.Runtime.CompilerServices.CompilerGeneratedAttribute$ 61 | ^System.CodeDom.Compiler.GeneratedCodeAttribute$ 62 | ^System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute$ 63 | 64 | 65 | 66 | 67 | 68 | 69 | .*\\atlmfc\\.* 70 | .*\\vctools\\.* 71 | .*\\public\\sdk\\.* 72 | .*\\microsoft sdks\\.* 73 | .*\\vc\\include\\.* 74 | .*\\cpplinq\\Test\\.* 75 | .*\\cpplinq\\CppLinq2013\.UnitTest\\.* 76 | 77 | 78 | 79 | 80 | 81 | 82 | .*microsoft.* 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | ^B77A5C561934E089$ 91 | ^B03F5F7F11D50A3A$ 92 | ^31BF3856AD364E35$ 93 | ^89845DCD8080CC91$ 94 | ^71E9BCE111E9429C$ 95 | ^8F50407C4E9E73B6$ 96 | ^E361AF139669C375$ 97 | 98 | 99 | 100 | 101 | 102 | True 103 | True 104 | True 105 | False 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /CppLinq.Mini/CppLinq2012.Mini.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50} 23 | Win32Proj 24 | CppLinqMini 25 | 26 | 27 | 28 | Application 29 | true 30 | v110 31 | Unicode 32 | 33 | 34 | Application 35 | true 36 | v110 37 | Unicode 38 | 39 | 40 | Application 41 | false 42 | v110 43 | true 44 | Unicode 45 | 46 | 47 | Application 48 | false 49 | v110 50 | true 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | true 71 | $(SolutionDir)Output\$(Configuration)\ 72 | Intermediate\$(Configuration)\ 73 | 74 | 75 | true 76 | 77 | 78 | false 79 | $(SolutionDir)Output\$(Configuration)\ 80 | Intermediate\$(Configuration)\ 81 | 82 | 83 | false 84 | $(SolutionDir)Output\$(Configuration)\ 85 | Intermediate\$(Configuration)\ 86 | 87 | 88 | 89 | Use 90 | Level3 91 | Disabled 92 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 93 | true 94 | 95 | 96 | Console 97 | true 98 | 99 | 100 | 101 | 102 | Use 103 | Level3 104 | Disabled 105 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | Use 117 | MaxSpeed 118 | true 119 | true 120 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 121 | true 122 | 123 | 124 | Console 125 | true 126 | true 127 | true 128 | 129 | 130 | 131 | 132 | Level3 133 | Use 134 | MaxSpeed 135 | true 136 | true 137 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 138 | true 139 | 140 | 141 | Console 142 | true 143 | true 144 | true 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | Create 154 | Create 155 | Create 156 | Create 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /Test/CppLinq2012.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {B2C5078E-E859-4BF8-A799-75653FE524AB} 23 | Win32Proj 24 | CppLinq 25 | 26 | 27 | 28 | Application 29 | true 30 | v110 31 | Unicode 32 | 33 | 34 | Application 35 | true 36 | v110 37 | Unicode 38 | 39 | 40 | Application 41 | false 42 | v110 43 | true 44 | Unicode 45 | 46 | 47 | Application 48 | false 49 | v110 50 | true 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | true 71 | $(SolutionDir)Output\$(Configuration)\ 72 | Intermediate\$(Configuration)\ 73 | 74 | 75 | true 76 | $(SolutionDir)Output\$(Configuration)\ 77 | Intermediate\$(Configuration)\ 78 | 79 | 80 | false 81 | $(SolutionDir)Output\$(Configuration)\ 82 | Intermediate\$(Configuration)\ 83 | 84 | 85 | false 86 | $(SolutionDir)Output\$(Configuration)\ 87 | Intermediate\$(Configuration)\ 88 | 89 | 90 | 91 | Use 92 | Level4 93 | Disabled 94 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 95 | true 96 | 97 | 98 | Console 99 | true 100 | 101 | 102 | 103 | 104 | Use 105 | Level4 106 | Disabled 107 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | 110 | 111 | Console 112 | true 113 | 114 | 115 | 116 | 117 | Level4 118 | Use 119 | MaxSpeed 120 | true 121 | true 122 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 123 | true 124 | 125 | 126 | Console 127 | true 128 | true 129 | true 130 | 131 | 132 | 133 | 134 | Level4 135 | Use 136 | MaxSpeed 137 | true 138 | true 139 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 140 | true 141 | 142 | 143 | Console 144 | true 145 | true 146 | true 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | Create 157 | Create 158 | Create 159 | Create 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /CppLinq.Mini/CppLinq2013.Mini.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {4CE7EBDE-D1A2-4B5D-853C-921668821E50} 23 | Win32Proj 24 | CppLinqMini 25 | 26 | 27 | 28 | Application 29 | true 30 | v120 31 | Unicode 32 | 33 | 34 | Application 35 | true 36 | v120 37 | Unicode 38 | 39 | 40 | Application 41 | false 42 | v120 43 | true 44 | Unicode 45 | 46 | 47 | Application 48 | false 49 | v120 50 | true 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | true 71 | $(SolutionDir)Output\$(Configuration)\ 72 | Intermediate2013\$(Configuration)\ 73 | 74 | 75 | true 76 | Intermediate2013\$(Configuration)\ 77 | $(SolutionDir)Output\$(Configuration)\ 78 | 79 | 80 | false 81 | $(SolutionDir)Output\$(Configuration)\ 82 | Intermediate2013\$(Configuration)\ 83 | 84 | 85 | false 86 | $(SolutionDir)Output\$(Configuration)\ 87 | Intermediate2013\$(Configuration)\ 88 | 89 | 90 | 91 | Use 92 | Level3 93 | Disabled 94 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 95 | true 96 | 97 | 98 | Console 99 | true 100 | 101 | 102 | 103 | 104 | Use 105 | Level3 106 | Disabled 107 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | 110 | 111 | Console 112 | true 113 | 114 | 115 | 116 | 117 | Level3 118 | Use 119 | MaxSpeed 120 | true 121 | true 122 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 123 | true 124 | 125 | 126 | Console 127 | true 128 | true 129 | true 130 | 131 | 132 | 133 | 134 | Level3 135 | Use 136 | MaxSpeed 137 | true 138 | true 139 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 140 | true 141 | 142 | 143 | Console 144 | true 145 | true 146 | true 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | Create 156 | Create 157 | Create 158 | Create 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /Test/CppLinq2013.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {B2C5078E-E859-4BF8-A799-75653FE524AB} 23 | Win32Proj 24 | CppLinq 25 | 26 | 27 | 28 | Application 29 | true 30 | v120 31 | Unicode 32 | 33 | 34 | Application 35 | true 36 | v120 37 | Unicode 38 | 39 | 40 | Application 41 | false 42 | v120 43 | true 44 | Unicode 45 | 46 | 47 | Application 48 | false 49 | v120 50 | true 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | true 71 | $(SolutionDir)Output\$(Configuration)\ 72 | Intermediate2013\$(Configuration)\ 73 | 74 | 75 | true 76 | $(SolutionDir)Output\$(Configuration)\ 77 | Intermediate2013\$(Configuration)\ 78 | 79 | 80 | false 81 | $(SolutionDir)Output\$(Configuration)\ 82 | Intermediate2013\$(Configuration)\ 83 | 84 | 85 | false 86 | $(SolutionDir)Output\$(Configuration)\ 87 | Intermediate2013\$(Configuration)\ 88 | 89 | 90 | 91 | Use 92 | Level4 93 | Disabled 94 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 95 | true 96 | 97 | 98 | Console 99 | true 100 | 101 | 102 | 103 | 104 | Use 105 | Level4 106 | Disabled 107 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | 110 | 111 | Console 112 | true 113 | 114 | 115 | 116 | 117 | Level4 118 | Use 119 | MaxSpeed 120 | true 121 | true 122 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 123 | true 124 | Speed 125 | 126 | 127 | Console 128 | true 129 | true 130 | true 131 | 132 | 133 | 134 | 135 | Level4 136 | Use 137 | MaxSpeed 138 | true 139 | true 140 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 141 | true 142 | 143 | 144 | Console 145 | true 146 | true 147 | true 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | Create 159 | Create 160 | Create 161 | Create 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /CppLinq2013.UnitTest/CppLinq2013.UnitTest.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {081E2554-9A17-45E3-9264-DC677FCE8DA2} 23 | Win32Proj 24 | CppLinq2013UnitTest 25 | 26 | 27 | 28 | DynamicLibrary 29 | true 30 | v120 31 | Unicode 32 | false 33 | 34 | 35 | DynamicLibrary 36 | true 37 | v120 38 | Unicode 39 | false 40 | 41 | 42 | DynamicLibrary 43 | false 44 | v120 45 | true 46 | Unicode 47 | false 48 | 49 | 50 | DynamicLibrary 51 | false 52 | v120 53 | true 54 | Unicode 55 | false 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | Intermediate2013\$(Configuration)\ 76 | $(SolutionDir)Output\$(Configuration)\ 77 | 78 | 79 | true 80 | Intermediate2013\$(Configuration)\ 81 | $(SolutionDir)Output\$(Configuration)\ 82 | 83 | 84 | true 85 | $(SolutionDir)Output\$(Configuration)\ 86 | Intermediate2013\$(Configuration)\ 87 | 88 | 89 | true 90 | $(SolutionDir)Output\$(Configuration)\ 91 | Intermediate2013\$(Configuration)\ 92 | 93 | 94 | 95 | Use 96 | Level3 97 | Disabled 98 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 99 | WIN32;_DEBUG;%(PreprocessorDefinitions) 100 | true 101 | 102 | 103 | Windows 104 | true 105 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 106 | 107 | 108 | 109 | 110 | Use 111 | Level3 112 | Disabled 113 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 114 | WIN32;_DEBUG;%(PreprocessorDefinitions) 115 | true 116 | 117 | 118 | Windows 119 | true 120 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 121 | 122 | 123 | 124 | 125 | Level3 126 | Use 127 | MaxSpeed 128 | true 129 | true 130 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 131 | WIN32;NDEBUG;%(PreprocessorDefinitions) 132 | true 133 | 134 | 135 | Windows 136 | true 137 | true 138 | true 139 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 140 | 141 | 142 | 143 | 144 | Level3 145 | Use 146 | MaxSpeed 147 | true 148 | true 149 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 150 | WIN32;NDEBUG;%(PreprocessorDefinitions) 151 | true 152 | 153 | 154 | Windows 155 | true 156 | true 157 | true 158 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | Create 167 | Create 168 | Create 169 | Create 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /Test/CppLinqTests.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------------------- 2 | // Copyright (c) Mårten Rånge. 3 | // ---------------------------------------------------------------------------------------------- 4 | // This source code is subject to terms and conditions of the Microsoft Public License. A 5 | // copy of the license can be found in the License.html file at the root of this distribution. 6 | // If you cannot locate the Microsoft Public License, please send an email to 7 | // dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 8 | // by the terms of the Microsoft Public License. 9 | // ---------------------------------------------------------------------------------------------- 10 | // You must not remove this notice, or any other, from this software. 11 | // ---------------------------------------------------------------------------------------------- 12 | #include "stdafx.h" 13 | // ---------------------------------------------------------------------------------------------- 14 | #ifdef _MSC_VER 15 | # pragma warning (disable:4100) 16 | # pragma warning (disable:4996) 17 | #endif 18 | // ---------------------------------------------------------------------------------------------- 19 | #ifdef _MSC_VER 20 | # include 21 | #endif 22 | // ---------------------------------------------------------------------------------------------- 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | // ---------------------------------------------------------------------------------------------- 33 | #include 34 | #include 35 | // ---------------------------------------------------------------------------------------------- 36 | #include "../CppLinq/cpplinq.hpp" 37 | // ---------------------------------------------------------------------------------------------- 38 | #define TEST_PRELUDE() test_prelude(__FILE__, __LINE__, __FUNCTION__) 39 | #define TEST_ASSERT(expected, found) test_assert(__FILE__, __LINE__, expected, #expected, found, #found, (expected == found)) 40 | #define PRINT_INDEX(idx) print_index (#idx, idx); 41 | // ---------------------------------------------------------------------------------------------- 42 | namespace 43 | { 44 | 45 | struct customer 46 | { 47 | std::size_t id ; 48 | std::string first_name ; 49 | std::string last_name ; 50 | 51 | customer (std::size_t id = 0, std::string first_name = "", std::string last_name = "") 52 | : id (std::move (id)) 53 | , first_name (std::move (first_name)) 54 | , last_name (std::move (last_name)) 55 | { 56 | } 57 | 58 | customer & operator= (customer const & c) 59 | { 60 | if (std::addressof (c) == this) 61 | { 62 | return *this; 63 | } 64 | 65 | id = c.id ; 66 | first_name = c.first_name ; 67 | last_name = c.last_name ; 68 | 69 | return *this; 70 | } 71 | 72 | customer (customer const & c) 73 | : id (c.id) 74 | , first_name (c.first_name) 75 | , last_name (c.last_name) 76 | { 77 | } 78 | 79 | customer (customer && c) 80 | : id (std::move (c.id)) 81 | , first_name (std::move (c.first_name)) 82 | , last_name (std::move (c.last_name)) 83 | { 84 | } 85 | 86 | bool operator==(customer const & c) const 87 | { 88 | return id == c.id && first_name == c.first_name && last_name == c.last_name; 89 | } 90 | 91 | bool operator !=(customer const & c) const 92 | { 93 | return !(*this == c); 94 | } 95 | 96 | bool operator<(customer const & c) const 97 | { 98 | return id < c.id; 99 | } 100 | }; 101 | 102 | struct customer_address 103 | { 104 | std::size_t id ; 105 | std::size_t customer_id ; 106 | std::string country ; 107 | 108 | customer_address (std::size_t id, std::size_t customer_id, std::string country) 109 | : id (std::move (id)) 110 | , customer_id (std::move (customer_id)) 111 | , country (std::move (country)) 112 | { 113 | } 114 | 115 | }; 116 | 117 | struct player 118 | { 119 | std::size_t id; 120 | }; 121 | 122 | struct game 123 | { 124 | std::size_t id ; 125 | std::set players ; 126 | }; 127 | 128 | template 129 | void ignore (T && v) CPPLINQ_NOEXCEPT 130 | { 131 | 132 | } 133 | 134 | template 135 | std::size_t get_array_size (TValueArray & a) 136 | { 137 | return cpplinq::detail::get_array_properties::size; 138 | } 139 | 140 | std::size_t get_even_counts (int const * is, std::size_t count) 141 | { 142 | auto c = 0U; 143 | for (auto index = 0U; index < count; ++index) 144 | { 145 | auto i = is[index]; 146 | if (i%2 == 0) 147 | { 148 | ++c; 149 | } 150 | } 151 | return c; 152 | } 153 | 154 | std::size_t errors = 0U; 155 | 156 | std::vector const empty_vector ; 157 | 158 | std::vector empty_customers ; 159 | 160 | customer const customers[] = 161 | { 162 | customer (1 , "Bill" , "Gates" ), 163 | customer (2 , "Steve" , "Jobs" ), 164 | customer (3 , "Richard" , "Stallman"), 165 | customer (4 , "Linus" , "Torvalds"), 166 | 167 | customer (11, "Steve" , "Ballmer" ), 168 | customer (12, "Tim" , "Cook" ), 169 | 170 | customer (21, "Melinda" , "Gates" ), 171 | }; 172 | std::size_t const count_of_customers = get_array_size (customers); 173 | 174 | customer_address const customer_addresses[] = 175 | { 176 | customer_address (2, 4, "Finland" ), 177 | customer_address (3, 4, "USA" ), 178 | customer_address (1, 1, "USA" ), 179 | }; 180 | std::size_t const count_of_customer_addresses = get_array_size (customer_addresses); 181 | 182 | customer const customers_set1[] = 183 | { 184 | customer (1 , "Bill" , "Gates" ), 185 | customer (2 , "Steve" , "Jobs" ), 186 | customer (3 , "Richard" , "Stallman"), 187 | customer (4 , "Linus" , "Torvalds"), 188 | customer (3 , "Richard" , "Stallman"), 189 | customer (2 , "Steve" , "Jobs" ), 190 | customer (1 , "Bill" , "Gates" ), 191 | }; 192 | 193 | customer const customers_set2[] = 194 | { 195 | customer (1 , "Bill" , "Gates" ), 196 | customer (11, "Steve" , "Ballmer" ), 197 | customer (12, "Tim" , "Cook" ), 198 | }; 199 | 200 | int const ints[] = {3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,8,4,6,2,6,4,3,3,8,3,2,7,9,5}; 201 | std::size_t const count_of_ints = get_array_size (ints); 202 | 203 | std::size_t const even_count_of_ints = get_even_counts (ints, count_of_ints); 204 | 205 | int const simple_ints[] = {1,2,3,4,5,6,7,8,9}; 206 | std::size_t const count_of_simple_ints = get_array_size (simple_ints); 207 | 208 | int const set1[] = {5,4,3,2,1,2,3,4,5}; 209 | std::size_t const count_of_set1 = get_array_size (set1); 210 | 211 | int const set2[] = {9,8,4,5,6,7,1,8,9}; 212 | std::size_t const count_of_set2 = get_array_size (set2); 213 | 214 | double const double_set[] = {-1.0,0.0,2.0}; 215 | std::size_t const count_of_double_set = get_array_size (double_set); 216 | 217 | std::set empty_game_set ; 218 | 219 | auto is_even = [](int i) {return i%2==0;}; 220 | auto is_odd = [](int i) {return i%2==1;}; 221 | auto smaller_than_five = [](int i) {return i < 5;}; 222 | auto greater_than_five = [](int i) {return i > 5;}; 223 | auto double_it = [](int i) {return i+i;}; 224 | auto sum_aggregator = [](int s, int i) {return s+i;}; 225 | auto mul_aggregator = [](int s, int i) {return s*i;}; 226 | auto to_string = [](int i) -> std::string {std::stringstream sstr; sstr< (index)); // VS doesn't support %zu yet 231 | } 232 | 233 | void test_prelude ( 234 | char const * file 235 | , int line_no 236 | , char const * test 237 | ) 238 | { 239 | printf ( 240 | "%s(%d): RUNNING: %s\n" 241 | , file 242 | , line_no 243 | , test 244 | ); 245 | } 246 | 247 | bool test_assert ( 248 | char const * file 249 | , int line_no 250 | , bool expected 251 | , char const * expected_name 252 | , bool found 253 | , char const * found_name 254 | , bool result 255 | ) 256 | { 257 | if (!result) 258 | { 259 | ++errors; 260 | printf ( 261 | "%s(%d): ERROR_EXPECTED: %s(%s), FOUND: %s(%s)\n" 262 | , file 263 | , line_no 264 | , expected ? "true" : "false" 265 | , expected_name 266 | , found ? "true" : "false" 267 | , found_name 268 | ); 269 | } 270 | 271 | return result; 272 | } 273 | 274 | bool test_assert ( 275 | char const * file 276 | , int line_no 277 | , std::string expected 278 | , char const * expected_name 279 | , std::string found 280 | , char const * found_name 281 | , bool result 282 | ) 283 | { 284 | if (!result) 285 | { 286 | ++errors; 287 | printf ( 288 | "%s(%d): ERROR_EXPECTED: %s(%s), FOUND: %s(%s)\n" 289 | , file 290 | , line_no 291 | , expected.c_str () 292 | , expected_name 293 | , found.c_str () 294 | , found_name 295 | ); 296 | } 297 | 298 | return result; 299 | } 300 | 301 | bool test_assert ( 302 | char const * file 303 | , int line_no 304 | , int expected 305 | , char const * expected_name 306 | , int found 307 | , char const * found_name 308 | , bool result 309 | ) 310 | { 311 | if (!result) 312 | { 313 | ++errors; 314 | printf ( 315 | "%s(%d): ERROR_EXPECTED: %d(%s), FOUND: %d(%s)\n" 316 | , file 317 | , line_no 318 | , expected 319 | , expected_name 320 | , found 321 | , found_name 322 | ); 323 | } 324 | 325 | return result; 326 | } 327 | 328 | bool test_assert ( 329 | char const * file 330 | , int line_no 331 | , double expected 332 | , char const * expected_name 333 | , double found 334 | , char const * found_name 335 | , bool result 336 | ) 337 | { 338 | if (!result) 339 | { 340 | ++errors; 341 | printf ( 342 | "%s(%d): ERROR_EXPECTED: %f(%s), FOUND: %f(%s)\n" 343 | , file 344 | , line_no 345 | , expected 346 | , expected_name 347 | , found 348 | , found_name 349 | ); 350 | } 351 | 352 | return result; 353 | } 354 | 355 | bool test_assert ( 356 | char const * file 357 | , int line_no 358 | , std::size_t expected 359 | , char const * expected_name 360 | , std::size_t found 361 | , char const * found_name 362 | , bool result 363 | ) 364 | { 365 | if (!result) 366 | { 367 | ++errors; 368 | printf ( 369 | "%s(%d): ERROR_EXPECTED: %u(%s), FOUND: %u(%s)\n" 370 | , file 371 | , line_no 372 | , static_cast (expected) // VS doesn't support %zu yet 373 | , expected_name 374 | , static_cast (found) // VS doesn't support %zu yet 375 | , found_name 376 | ); 377 | } 378 | 379 | return result; 380 | } 381 | 382 | 383 | bool test_assert ( 384 | char const * file 385 | , int line_no 386 | , customer expected 387 | , char const * expected_name 388 | , customer found 389 | , char const * found_name 390 | , bool result 391 | ) 392 | { 393 | if (!result) 394 | { 395 | ++errors; 396 | printf ( 397 | "%s(%d): ERROR_EXPECTED: (%u,%s,%s)(%s), FOUND: (%u,%s,%s)(%s)\n" 398 | , file 399 | , line_no 400 | , static_cast (expected.id), expected.first_name.c_str (), expected.last_name.c_str () // VS doesn't support %zu yet 401 | , expected_name 402 | , static_cast (found.id), found.first_name.c_str (), found.last_name.c_str () // VS doesn't support %zu yet 403 | , found_name 404 | ); 405 | } 406 | 407 | return result; 408 | } 409 | 410 | void test_int_at (std::size_t index, int v) 411 | { 412 | if ( 413 | TEST_ASSERT (true, (index < count_of_ints)) 414 | && TEST_ASSERT (ints[index], v) 415 | ) 416 | { 417 | } 418 | else 419 | { 420 | PRINT_INDEX (index); 421 | } 422 | } 423 | 424 | void test_opt () 425 | { 426 | using namespace cpplinq::detail; 427 | 428 | TEST_PRELUDE (); 429 | 430 | { 431 | opt o; 432 | TEST_ASSERT (false, o.has_value ()); 433 | 434 | // Test to make sure that 'if (o)' compiles 435 | if (o) 436 | { 437 | } 438 | } 439 | { 440 | opt o1; 441 | opt o2 (10); 442 | TEST_ASSERT (false, o1.has_value ()); 443 | TEST_ASSERT (true, o2.has_value ()); 444 | TEST_ASSERT (10, *o2); 445 | 446 | o1 = o1; 447 | o2 = o2; 448 | TEST_ASSERT (false, o1.has_value ()); 449 | TEST_ASSERT (true, o2.has_value ()); 450 | TEST_ASSERT (10, *o2); 451 | 452 | o1 = std::move (o1); 453 | o2 = std::move (o2); 454 | TEST_ASSERT (false, o1.has_value ()); 455 | TEST_ASSERT (true, o2.has_value ()); 456 | TEST_ASSERT (10, *o2); 457 | 458 | opt o3 (o2); 459 | opt o4 (o1); 460 | o3.swap (o4); 461 | TEST_ASSERT (false, o3.has_value ()); 462 | TEST_ASSERT (true, o4.has_value ()); 463 | TEST_ASSERT (10, *o4); 464 | 465 | o1.swap (o2); 466 | TEST_ASSERT (true, o1.has_value ()); 467 | TEST_ASSERT (10, *o1); 468 | TEST_ASSERT (false, o2.has_value ()); 469 | 470 | 471 | 472 | o2 = o1; 473 | TEST_ASSERT (true, o1.has_value ()); 474 | TEST_ASSERT (10, *o1); 475 | TEST_ASSERT (true, o2.has_value ()); 476 | TEST_ASSERT (10, *o2); 477 | 478 | o1 = 11; 479 | o2 = 12; 480 | TEST_ASSERT (true, o1.has_value ()); 481 | TEST_ASSERT (11, *o1); 482 | TEST_ASSERT (true, o2.has_value ()); 483 | TEST_ASSERT (12, *o2); 484 | 485 | } 486 | { 487 | opt o1; 488 | opt o2 ("Test"); 489 | 490 | TEST_ASSERT (false, o1.has_value ()); 491 | TEST_ASSERT (true, o2.has_value ()); 492 | TEST_ASSERT ("Test", *o2); 493 | TEST_ASSERT (4U, o2->size ()); 494 | 495 | o1 = "Test2"; 496 | o2 = "Test3"; 497 | TEST_ASSERT (true, o1.has_value ()); 498 | TEST_ASSERT ("Test2", *o1); 499 | TEST_ASSERT (true, o2.has_value ()); 500 | TEST_ASSERT ("Test3", *o2); 501 | 502 | o1.swap (o2); 503 | TEST_ASSERT (true, o1.has_value ()); 504 | TEST_ASSERT ("Test3", *o1); 505 | TEST_ASSERT (true, o2.has_value ()); 506 | TEST_ASSERT ("Test2", *o2); 507 | } 508 | 509 | { 510 | opt o (1); 511 | TEST_ASSERT (true, o.has_value ()); 512 | 513 | o.clear (); 514 | TEST_ASSERT (false, o.has_value ()); 515 | } 516 | } 517 | 518 | void test_lookup () 519 | { 520 | using namespace cpplinq; 521 | using namespace cpplinq::detail; 522 | 523 | TEST_PRELUDE (); 524 | 525 | { 526 | lookup lookup ( 527 | 16U 528 | , from (empty_customers) 529 | , [] (customer const & c){return c.id;} 530 | ); 531 | 532 | TEST_ASSERT (0U, lookup.size_of_keys ()); 533 | TEST_ASSERT (0U, lookup.size_of_values ()); 534 | 535 | { 536 | auto results = lookup[999] >> to_vector (); 537 | TEST_ASSERT (0U, results.size ()); 538 | } 539 | 540 | { 541 | auto results = lookup.range_of_values () >> to_vector (); 542 | TEST_ASSERT (0U, results.size ()); 543 | } 544 | } 545 | 546 | { 547 | lookup lookup ( 548 | 16U 549 | , from_array (customers) 550 | , [] (customer const & c){return c.id;} 551 | ); 552 | 553 | TEST_ASSERT (count_of_customers, lookup.size_of_keys ()); 554 | TEST_ASSERT (count_of_customers, lookup.size_of_values ()); 555 | 556 | { 557 | auto results = lookup.range_of_values () >> to_vector (); 558 | if (TEST_ASSERT (count_of_customers, results.size ())) 559 | { 560 | for (std::size_t iter = 0U; iter < count_of_customers; ++iter) 561 | { 562 | // As customers are sorted on id in the test data set 563 | // this is ok 564 | if (!TEST_ASSERT (customers[iter].id, results[iter].id)) 565 | { 566 | PRINT_INDEX (iter); 567 | } 568 | } 569 | } 570 | 571 | } 572 | 573 | for (auto customer : customers) 574 | { 575 | auto results = lookup[customer.id] >> to_vector (); 576 | if (TEST_ASSERT (1U, results.size ())) 577 | { 578 | auto result = results.front (); 579 | 580 | if (!TEST_ASSERT (customer.id, result.id)) 581 | { 582 | PRINT_INDEX (customer.id); 583 | } 584 | } 585 | else 586 | { 587 | PRINT_INDEX (customer.id); 588 | } 589 | } 590 | } 591 | 592 | { 593 | lookup lookup ( 594 | 16U 595 | , from_array (customer_addresses) 596 | , [] (customer_address const & ca){return ca.customer_id;} 597 | ); 598 | 599 | TEST_ASSERT (2U, lookup.size_of_keys ()); 600 | TEST_ASSERT (count_of_customer_addresses, lookup.size_of_values ()); 601 | 602 | { 603 | auto results = lookup.range_of_values () >> to_vector (); 604 | TEST_ASSERT (count_of_customer_addresses, results.size ()); 605 | } 606 | { 607 | auto results = lookup[1] >> to_vector (); 608 | if (TEST_ASSERT (1U, results.size ())) 609 | { 610 | auto result = results.front (); 611 | TEST_ASSERT (1U, result.id); 612 | } 613 | } 614 | 615 | { 616 | auto results = lookup[4] >> to_vector (); 617 | if (TEST_ASSERT (2U, results.size ())) 618 | { 619 | auto result1 = results[0]; 620 | TEST_ASSERT (2U, result1.id); 621 | 622 | auto result2 = results[1]; 623 | TEST_ASSERT (3U, result2.id); 624 | } 625 | } 626 | 627 | { 628 | auto results = lookup[999] >> to_vector (); 629 | TEST_ASSERT (0U, results.size ()); 630 | } 631 | } 632 | 633 | } 634 | 635 | void test_from () 636 | { 637 | using namespace cpplinq; 638 | 639 | TEST_PRELUDE (); 640 | 641 | { 642 | auto q = from (empty_vector); 643 | 644 | typedef decltype (q.front ()) return_type; 645 | static_assert ( 646 | std::is_reference::value 647 | , "from::front () must return reference" 648 | ); 649 | 650 | std::size_t index = 0U; 651 | 652 | while (q.next ()) 653 | { 654 | test_int_at (index, q.front ()); 655 | ++index; 656 | } 657 | TEST_ASSERT (0U, index); 658 | } 659 | { 660 | auto q = from_array (ints); 661 | 662 | typedef decltype (q.front ()) return_type; 663 | static_assert ( 664 | std::is_reference::value 665 | , "from::front () must return reference" 666 | ); 667 | 668 | auto index = 0U; 669 | 670 | while (q.next ()) 671 | { 672 | test_int_at (index, q.front ()); 673 | ++index; 674 | } 675 | TEST_ASSERT (count_of_ints, index); 676 | } 677 | { 678 | auto q = from_copy (empty_vector); 679 | 680 | typedef decltype (q.front ()) return_type; 681 | static_assert ( 682 | std::is_reference::value 683 | , "from::front () must return reference" 684 | ); 685 | 686 | std::size_t index = 0U; 687 | 688 | while (q.next ()) 689 | { 690 | test_int_at (index, q.front ()); 691 | ++index; 692 | } 693 | TEST_ASSERT (0U, index); 694 | } 695 | { 696 | std::vector is (ints, ints + count_of_ints); 697 | auto q = from_copy (is); 698 | 699 | typedef decltype (q.front ()) return_type; 700 | static_assert ( 701 | std::is_reference::value 702 | , "from::front () must return reference" 703 | ); 704 | 705 | auto index = 0U; 706 | 707 | while (q.next ()) 708 | { 709 | test_int_at (index, q.front ()); 710 | ++index; 711 | } 712 | TEST_ASSERT (count_of_ints, index); 713 | } 714 | { 715 | auto q = from_array (customers); 716 | typedef decltype (q.front ()) return_type; 717 | static_assert ( 718 | std::is_reference::value 719 | , "front () must return non-reference when value_type = customer" 720 | ); 721 | } 722 | { 723 | std::vector cs; 724 | auto q = from_copy (cs); 725 | typedef decltype (q.front ()) return_type; 726 | static_assert ( 727 | std::is_reference::value 728 | , "front () must return non-reference when value_type = customer" 729 | ); 730 | } 731 | } 732 | 733 | void test_range () 734 | { 735 | using namespace cpplinq; 736 | 737 | TEST_PRELUDE (); 738 | 739 | { 740 | auto r = range (10, 0); 741 | 742 | typedef decltype (r.front ()) return_type; 743 | static_assert ( 744 | !std::is_reference::value 745 | , "front () must return non-reference when value_type = int" 746 | ); 747 | 748 | bool isempty = !r.next (); 749 | 750 | TEST_ASSERT (true, isempty); 751 | } 752 | 753 | { 754 | auto start = 12; 755 | auto count = 10; 756 | auto index = start; 757 | 758 | auto q = range (start, count); 759 | 760 | typedef decltype (q.front ()) return_type; 761 | static_assert ( 762 | !std::is_reference::value 763 | , "front () must return non-reference when value_type = int" 764 | ); 765 | 766 | while (q.next ()) 767 | { 768 | if (!TEST_ASSERT (index, q.front ())) 769 | { 770 | PRINT_INDEX (index); 771 | } 772 | ++index; 773 | } 774 | TEST_ASSERT (start + count , index); 775 | } 776 | } 777 | 778 | void test_repeat () 779 | { 780 | using namespace cpplinq; 781 | 782 | TEST_PRELUDE (); 783 | 784 | { 785 | auto r = repeat (42, 0); 786 | 787 | typedef decltype (r.front ()) return_type; 788 | static_assert ( 789 | !std::is_reference::value 790 | , "front () must return non-reference when value_type = int" 791 | ); 792 | 793 | bool isempty = !r.next (); 794 | 795 | TEST_ASSERT (true, isempty); 796 | } 797 | 798 | { 799 | auto value = 42; 800 | int count = 10; 801 | int total = 0; 802 | 803 | auto r = repeat (value, count); 804 | 805 | typedef decltype (r.front ()) return_type; 806 | static_assert ( 807 | !std::is_reference::value 808 | , "front () must return non-reference when value_type = int" 809 | ); 810 | 811 | while (r.next ()) 812 | { 813 | if (!TEST_ASSERT (value, r.front ())) 814 | { 815 | PRINT_INDEX (total); 816 | } 817 | ++total; 818 | } 819 | TEST_ASSERT (total , count); 820 | } 821 | 822 | { 823 | auto value = customers[0]; 824 | int count = 10; 825 | int total = 0; 826 | 827 | auto r = repeat (value, count); 828 | 829 | while (r.next ()) 830 | { 831 | if (!TEST_ASSERT (value, r.front ())) 832 | { 833 | PRINT_INDEX (total); 834 | } 835 | ++total; 836 | } 837 | TEST_ASSERT (total , count); 838 | } 839 | } 840 | 841 | void test_empty () 842 | { 843 | using namespace cpplinq; 844 | 845 | TEST_PRELUDE (); 846 | 847 | { 848 | auto r = empty(); 849 | 850 | typedef decltype (r.front ()) return_type; 851 | static_assert ( 852 | !std::is_reference::value 853 | , "front () must return non-reference when value_type = int" 854 | ); 855 | 856 | bool isempty = !r.next (); 857 | 858 | TEST_ASSERT (true, isempty); 859 | } 860 | 861 | { 862 | auto r = empty(); 863 | 864 | bool isempty = !r.next (); 865 | 866 | TEST_ASSERT (true, isempty); 867 | } 868 | 869 | { 870 | auto customers = empty() >> to_list (); 871 | TEST_ASSERT (0U, customers.size ()); 872 | } 873 | 874 | } 875 | 876 | void test_singleton () 877 | { 878 | using namespace cpplinq; 879 | 880 | TEST_PRELUDE (); 881 | 882 | { 883 | auto singleton_result = singleton (1) >> to_vector (); 884 | TEST_ASSERT (1U, singleton_result.size ()); 885 | TEST_ASSERT (1, singleton_result[0]); 886 | } 887 | } 888 | 889 | void test_generate () 890 | { 891 | using namespace cpplinq; 892 | 893 | TEST_PRELUDE (); 894 | 895 | { 896 | auto x = -1; 897 | auto generate_result = 898 | generate ( 899 | [&]() 900 | { 901 | return (++x < 3) 902 | ? to_opt (x) 903 | : to_opt () 904 | ; 905 | }) 906 | >> to_vector () 907 | ; 908 | 909 | if (TEST_ASSERT (3U, generate_result.size ())) 910 | { 911 | TEST_ASSERT (0, generate_result[0]); 912 | TEST_ASSERT (1, generate_result[1]); 913 | TEST_ASSERT (2, generate_result[2]); 914 | } 915 | } 916 | } 917 | 918 | void test_set () 919 | { 920 | using namespace cpplinq; 921 | 922 | TEST_PRELUDE (); 923 | 924 | { 925 | auto count_result = from (empty_game_set) >> count (); 926 | TEST_ASSERT (0U, count_result); 927 | } 928 | 929 | { 930 | auto count_result = 931 | from (empty_game_set) 932 | >> select ([] (game * g) { return g->id; }) 933 | >> distinct () 934 | >> count () 935 | ; 936 | TEST_ASSERT (0U, count_result); 937 | } 938 | { 939 | // TODO: Test code for more complex select_many 940 | auto count_result = 941 | from (empty_game_set) 942 | >> where ([] (game * g) { return g != nullptr; }) 943 | >> select_many ( 944 | [] (game * g) 945 | { 946 | auto r = 947 | from (g->players) 948 | // >> where ([] (player * p) { return p != nullptr; }) 949 | // >> select ([] (player* p) { return p->id; }) 950 | ; 951 | return r; 952 | }) 953 | >> distinct () 954 | >> count () 955 | ; 956 | 957 | TEST_ASSERT (0U, count_result); 958 | } 959 | } 960 | 961 | void test_count () 962 | { 963 | using namespace cpplinq; 964 | 965 | TEST_PRELUDE (); 966 | 967 | { 968 | auto count_result = from (empty_vector) >> count (); 969 | TEST_ASSERT (0U, count_result); 970 | } 971 | 972 | { 973 | auto count_result = from_array (ints) >> count (); 974 | TEST_ASSERT (count_of_ints, count_result); 975 | } 976 | 977 | { 978 | auto count_result = from (empty_vector) >> count (is_even); 979 | TEST_ASSERT (0U, count_result); 980 | } 981 | 982 | { 983 | auto count_result = from_array (ints) >> count (is_even); 984 | TEST_ASSERT (even_count_of_ints, count_result); 985 | } 986 | 987 | } 988 | 989 | void test_any () 990 | { 991 | using namespace cpplinq; 992 | 993 | TEST_PRELUDE (); 994 | 995 | { 996 | auto any_result = from (empty_vector) >> any (); 997 | TEST_ASSERT (false, any_result); 998 | } 999 | 1000 | { 1001 | auto any_result = from_array (ints) >> any (); 1002 | TEST_ASSERT (true, any_result); 1003 | } 1004 | 1005 | { 1006 | auto any_result = from (empty_vector) >> any (is_even); 1007 | TEST_ASSERT (false, any_result); 1008 | } 1009 | 1010 | { 1011 | auto any_result = from_array (ints) >> any (is_even); 1012 | TEST_ASSERT (true, any_result); 1013 | } 1014 | } 1015 | 1016 | void test_first () 1017 | { 1018 | using namespace cpplinq; 1019 | 1020 | TEST_PRELUDE (); 1021 | 1022 | std::string expected_on_failure ("sequence_empty_exception"); 1023 | 1024 | { 1025 | sequence_empty_exception caught_exception; 1026 | try 1027 | { 1028 | int first_result = from (empty_vector) >> first (); 1029 | ignore (first_result); 1030 | } 1031 | catch (sequence_empty_exception const & ex) 1032 | { 1033 | caught_exception = ex; 1034 | } 1035 | TEST_ASSERT (expected_on_failure, caught_exception.what ()); 1036 | } 1037 | 1038 | { 1039 | int first_result = from_array (ints) >> first (); 1040 | TEST_ASSERT (3, first_result); 1041 | } 1042 | 1043 | { 1044 | sequence_empty_exception caught_exception; 1045 | try 1046 | { 1047 | int first_result = from (empty_vector) >> first (is_even); 1048 | ignore (first_result); 1049 | } 1050 | catch (sequence_empty_exception const & ex) 1051 | { 1052 | caught_exception = ex; 1053 | } 1054 | TEST_ASSERT (expected_on_failure, caught_exception.what ()); 1055 | } 1056 | 1057 | { 1058 | int first_result = from_array (ints) >> first (is_even); 1059 | TEST_ASSERT (4, first_result); 1060 | } 1061 | 1062 | { 1063 | // Issue: https://cpplinq.codeplex.com/workitem/15 1064 | // Reported by: Sepidar 1065 | auto result = 1066 | range (0, 3) 1067 | >> where ([](int i) {return i % 2 == 1;}) 1068 | >> orderby ([](int i) {return i;}) 1069 | >> first () 1070 | ; 1071 | 1072 | TEST_ASSERT (1, result); 1073 | } 1074 | 1075 | } 1076 | 1077 | void test_first_or_default () 1078 | { 1079 | using namespace cpplinq; 1080 | 1081 | TEST_PRELUDE (); 1082 | 1083 | { 1084 | int first_result = from (empty_vector) >> first_or_default (); 1085 | TEST_ASSERT (0, first_result); 1086 | } 1087 | 1088 | { 1089 | int first_result = from_array (ints) >> first_or_default (); 1090 | TEST_ASSERT (3, first_result); 1091 | } 1092 | 1093 | { 1094 | int first_result = from (empty_vector) >> first_or_default (is_even); 1095 | TEST_ASSERT (0, first_result); 1096 | } 1097 | 1098 | { 1099 | int first_result = from_array (ints) >> first_or_default (is_even); 1100 | TEST_ASSERT (4, first_result); 1101 | } 1102 | 1103 | } 1104 | 1105 | void test_last_or_default () 1106 | { 1107 | using namespace cpplinq; 1108 | 1109 | TEST_PRELUDE (); 1110 | 1111 | { 1112 | int first_result = from (empty_vector) >> last_or_default (); 1113 | TEST_ASSERT (0, first_result); 1114 | } 1115 | 1116 | { 1117 | int first_result = from_array (ints) >> last_or_default (); 1118 | TEST_ASSERT (5, first_result); 1119 | } 1120 | 1121 | { 1122 | int first_result = from (empty_vector) >> last_or_default (is_even); 1123 | TEST_ASSERT (0, first_result); 1124 | } 1125 | 1126 | { 1127 | int first_result = from_array (ints) >> last_or_default (is_even); 1128 | TEST_ASSERT (2, first_result); 1129 | } 1130 | } 1131 | 1132 | void test_sum () 1133 | { 1134 | using namespace cpplinq; 1135 | 1136 | TEST_PRELUDE (); 1137 | 1138 | { 1139 | int sum_result = from (empty_vector) >> sum (); 1140 | TEST_ASSERT (0, sum_result); 1141 | } 1142 | 1143 | { 1144 | int sum_of_ints = std::accumulate (ints, ints + count_of_ints, 0); 1145 | int sum_result = from_array (ints) >> sum (); 1146 | TEST_ASSERT (sum_of_ints, sum_result); 1147 | } 1148 | 1149 | { 1150 | int sum_result = from (empty_vector) >> sum (double_it); 1151 | TEST_ASSERT (0, sum_result); 1152 | } 1153 | 1154 | { 1155 | int sum_of_ints = std::accumulate (ints, ints + count_of_ints, 0); 1156 | int sum_result = from_array (ints) >> sum (double_it); 1157 | TEST_ASSERT (2*sum_of_ints, sum_result); 1158 | } 1159 | 1160 | { 1161 | std::size_t sum_result = from_array (customers) >> sum ([] (customer const & c) { return c.id; }); 1162 | TEST_ASSERT (54U, sum_result); 1163 | } 1164 | 1165 | } 1166 | 1167 | void test_min () 1168 | { 1169 | using namespace cpplinq; 1170 | 1171 | TEST_PRELUDE (); 1172 | 1173 | { 1174 | int min_result = from (empty_vector) >> min (); 1175 | TEST_ASSERT (INT_MAX, min_result); 1176 | } 1177 | 1178 | { 1179 | int min_result = from_array (ints) >> min (); 1180 | TEST_ASSERT (1, min_result); 1181 | } 1182 | 1183 | { 1184 | int min_result = from (empty_vector) >> min (double_it); 1185 | TEST_ASSERT (INT_MAX, min_result); 1186 | } 1187 | 1188 | { 1189 | int min_result = from_array (ints) >> min (double_it); 1190 | TEST_ASSERT (2, min_result); 1191 | } 1192 | 1193 | { 1194 | double min_result = from_array (double_set) >> min (); 1195 | TEST_ASSERT (-1.0, min_result); 1196 | } 1197 | 1198 | { 1199 | std::size_t min_result = from_array (customers) >> min ([] (customer const & c) { return c.id; }); 1200 | TEST_ASSERT (1U, min_result); 1201 | } 1202 | } 1203 | 1204 | void test_avg () 1205 | { 1206 | using namespace cpplinq; 1207 | 1208 | TEST_PRELUDE (); 1209 | 1210 | { 1211 | int avg_result = from (empty_vector) >> avg (); 1212 | TEST_ASSERT (0, avg_result); 1213 | } 1214 | 1215 | { 1216 | int avg_result = from_array (ints) >> avg (); 1217 | TEST_ASSERT (4, avg_result); 1218 | } 1219 | 1220 | { 1221 | int avg_result = from (empty_vector) >> avg (double_it); 1222 | TEST_ASSERT (0, avg_result); 1223 | } 1224 | 1225 | { 1226 | int avg_result = from_array (ints) >> avg (double_it); 1227 | TEST_ASSERT (9, avg_result); 1228 | } 1229 | 1230 | { 1231 | std::size_t avg_result = from_array (customers) >> avg ([] (customer const & c) { return c.id; }); 1232 | TEST_ASSERT (7U, avg_result); 1233 | } 1234 | } 1235 | 1236 | void test_max () 1237 | { 1238 | using namespace cpplinq; 1239 | 1240 | TEST_PRELUDE (); 1241 | 1242 | { 1243 | int max_result = from (empty_vector) >> max (); 1244 | TEST_ASSERT (INT_MIN, max_result); 1245 | } 1246 | 1247 | { 1248 | int max_result = from_array (ints) >> max (); 1249 | TEST_ASSERT (9, max_result); 1250 | } 1251 | 1252 | { 1253 | int max_result = from (empty_vector) >> max (double_it); 1254 | TEST_ASSERT (INT_MIN, max_result); 1255 | } 1256 | 1257 | { 1258 | int max_result = from_array (ints) >> max (double_it); 1259 | TEST_ASSERT (18, max_result); 1260 | } 1261 | 1262 | { 1263 | double max_result = from_array (double_set) >> max (); 1264 | TEST_ASSERT (2.0, max_result); 1265 | } 1266 | 1267 | { 1268 | std::size_t max_result = from_array (customers) >> max ([] (customer const & c) { return c.id; }); 1269 | TEST_ASSERT (21U, max_result); 1270 | } 1271 | 1272 | } 1273 | 1274 | void test_concatenate () 1275 | { 1276 | using namespace cpplinq; 1277 | 1278 | TEST_PRELUDE (); 1279 | 1280 | { 1281 | std::wstring concatenate_result = 1282 | from (empty_vector) 1283 | >> select ([] (int i){return std::wstring ();}) 1284 | >> concatenate (L"") 1285 | ; 1286 | TEST_ASSERT (true, concatenate_result.empty ()); 1287 | } 1288 | 1289 | { 1290 | std::string concatenate_result = 1291 | from_array (customers) 1292 | >> select ([](customer const & c){return c.last_name;}) 1293 | >> concatenate (", ") 1294 | ; 1295 | 1296 | TEST_ASSERT ("Gates, Jobs, Stallman, Torvalds, Ballmer, Cook, Gates", concatenate_result); 1297 | } 1298 | } 1299 | 1300 | void test_for_each () 1301 | { 1302 | using namespace cpplinq; 1303 | 1304 | TEST_PRELUDE (); 1305 | 1306 | { 1307 | std::size_t index = 0U; 1308 | from (empty_vector) >> for_each ([&](int i){test_int_at (index, i); ++index;}); 1309 | TEST_ASSERT (0U, index); 1310 | } 1311 | 1312 | { 1313 | auto index = 0U; 1314 | from_array (ints) >> for_each ([&](int i){test_int_at (index, i); ++index;}); 1315 | TEST_ASSERT (count_of_ints, index); 1316 | 1317 | } 1318 | } 1319 | 1320 | void test_all () 1321 | { 1322 | using namespace cpplinq; 1323 | 1324 | TEST_PRELUDE (); 1325 | 1326 | { 1327 | std::size_t index = 0U; 1328 | auto all_result = from (empty_vector) >> all ([&](int i)-> bool {test_int_at (index, i); ++index; return true;}); 1329 | TEST_ASSERT (true, all_result); 1330 | TEST_ASSERT (0U, index); 1331 | } 1332 | 1333 | { 1334 | auto index = 0U; 1335 | auto all_result = from_array (ints) >> all ([&](int i)-> bool {test_int_at (index, i); ++index; return true;}); 1336 | TEST_ASSERT (true, all_result); 1337 | TEST_ASSERT (count_of_ints, index); 1338 | 1339 | } 1340 | 1341 | { 1342 | std::size_t index = 0U; 1343 | auto all_result = from_array (ints) >> all ([&](int i)-> bool {test_int_at (index, i); ++index; return index < 10;}); 1344 | TEST_ASSERT (false, all_result); 1345 | TEST_ASSERT (10U, index); 1346 | 1347 | } 1348 | } 1349 | 1350 | void test_to_vector () 1351 | { 1352 | using namespace cpplinq; 1353 | 1354 | TEST_PRELUDE (); 1355 | 1356 | { 1357 | std::vector to_vector_result = from (empty_vector) >> to_vector (); 1358 | TEST_ASSERT (0U, to_vector_result.size ()); 1359 | } 1360 | 1361 | { 1362 | std::vector to_vector_result = from_array (ints) >> to_vector (); 1363 | TEST_ASSERT (count_of_ints, to_vector_result.size ()); 1364 | for (auto index = 0U; index < to_vector_result.size (); ++index) 1365 | { 1366 | test_int_at (index, to_vector_result[index]); 1367 | } 1368 | } 1369 | } 1370 | 1371 | void test_to_map () 1372 | { 1373 | using namespace cpplinq; 1374 | 1375 | TEST_PRELUDE (); 1376 | 1377 | { 1378 | std::map to_map_result = from (empty_vector) >> to_map ([](int i){return i;}); 1379 | TEST_ASSERT (0U, to_map_result.size ()); 1380 | } 1381 | 1382 | { 1383 | auto to_map_result = from_array (customers) >> to_map ([](customer const & c){return c.id;}); 1384 | TEST_ASSERT (count_of_customers, to_map_result.size ()); 1385 | 1386 | for (auto index = 0U; index < count_of_customers; ++index) 1387 | { 1388 | auto c1 = customers[index]; 1389 | auto find_c2 = to_map_result.find (c1.id); 1390 | if (TEST_ASSERT (true, (find_c2 != to_map_result.end ()))) 1391 | { 1392 | auto c2 = find_c2->second; 1393 | 1394 | if ( 1395 | TEST_ASSERT (c1.id, c2.id) 1396 | && TEST_ASSERT (c1.first_name, c2.first_name) 1397 | && TEST_ASSERT (c1.last_name, c2.last_name) 1398 | ) 1399 | { 1400 | } 1401 | else 1402 | { 1403 | PRINT_INDEX (index); 1404 | } 1405 | } 1406 | } 1407 | } 1408 | } 1409 | 1410 | void test_to_lookup () 1411 | { 1412 | using namespace cpplinq; 1413 | using namespace cpplinq::detail; 1414 | 1415 | TEST_PRELUDE (); 1416 | 1417 | { 1418 | auto lookup = from (empty_customers) >> to_lookup ([] (customer const & c){return c.id;}); 1419 | 1420 | TEST_ASSERT (0U, lookup.size_of_keys ()); 1421 | TEST_ASSERT (0U, lookup.size_of_values ()); 1422 | } 1423 | 1424 | { 1425 | auto lookup = from_array (customers) >> to_lookup ([] (customer const & c){return c.id;}); 1426 | 1427 | TEST_ASSERT (count_of_customers, lookup.size_of_keys ()); 1428 | TEST_ASSERT (count_of_customers, lookup.size_of_values ()); 1429 | 1430 | for (auto customer : customers) 1431 | { 1432 | auto results = lookup[customer.id] >> to_vector (); 1433 | if (TEST_ASSERT (1U, results.size ())) 1434 | { 1435 | auto result = results.front (); 1436 | 1437 | if (!TEST_ASSERT (customer.id, result.id)) 1438 | { 1439 | PRINT_INDEX (customer.id); 1440 | } 1441 | } 1442 | else 1443 | { 1444 | PRINT_INDEX (customer.id); 1445 | } 1446 | } 1447 | } 1448 | 1449 | { 1450 | auto lookup = from_array (customer_addresses) >> to_lookup ([] (customer_address const & ca){return ca.customer_id;}); 1451 | 1452 | TEST_ASSERT (2U, lookup.size_of_keys ()); 1453 | TEST_ASSERT (count_of_customer_addresses, lookup.size_of_values ()); 1454 | 1455 | { 1456 | auto results = lookup[1] >> to_vector (); 1457 | if (TEST_ASSERT (1U, results.size ())) 1458 | { 1459 | auto result = results.front (); 1460 | TEST_ASSERT (1U, result.id); 1461 | } 1462 | } 1463 | 1464 | { 1465 | auto results = lookup[4] >> to_vector (); 1466 | if (TEST_ASSERT (2U, results.size ())) 1467 | { 1468 | auto result1 = results[0]; 1469 | TEST_ASSERT (2U, result1.id); 1470 | 1471 | auto result2 = results[1]; 1472 | TEST_ASSERT (3U, result2.id); 1473 | } 1474 | } 1475 | 1476 | { 1477 | auto results = lookup[999] >> to_vector (); 1478 | TEST_ASSERT (0U, results.size ()); 1479 | } 1480 | } 1481 | 1482 | // code coverage test 1483 | { 1484 | auto lookup = empty() >> to_lookup ([] (int i) {return i;}); 1485 | 1486 | auto q = lookup[999]; 1487 | 1488 | TEST_ASSERT (false, q.next ()); 1489 | TEST_ASSERT (false, q.next ()); 1490 | } 1491 | } 1492 | 1493 | void test_to_list () 1494 | { 1495 | using namespace cpplinq; 1496 | 1497 | TEST_PRELUDE (); 1498 | 1499 | { 1500 | std::list to_list_result = from (empty_vector) >> to_list (); 1501 | TEST_ASSERT (0U, to_list_result.size ()); 1502 | } 1503 | 1504 | { 1505 | std::list to_list_result = from_array (ints) >> to_list (); 1506 | TEST_ASSERT (count_of_ints, to_list_result.size ()); 1507 | 1508 | auto pos = to_list_result.begin (); 1509 | for (auto index = 0U; index < to_list_result.size (); ++index) 1510 | { 1511 | test_int_at (index, *pos++); 1512 | } 1513 | } 1514 | } 1515 | 1516 | void test_container () 1517 | { 1518 | using namespace cpplinq; 1519 | using namespace cpplinq::experimental; 1520 | 1521 | TEST_PRELUDE (); 1522 | 1523 | { 1524 | auto container_result = from (empty_vector) >> container (); 1525 | std::vector v (container_result.begin (), container_result.end ()); 1526 | TEST_ASSERT (0U, v.size ()); 1527 | } 1528 | 1529 | { 1530 | auto container_result = from_iterators (ints, ints + count_of_ints) >> container (); 1531 | std::vector v (container_result.begin (), container_result.end ()); 1532 | if (TEST_ASSERT (count_of_ints, v.size ())) 1533 | { 1534 | for (auto index = 0U; index < count_of_ints; ++index) 1535 | { 1536 | test_int_at (index, v[index]); 1537 | } 1538 | } 1539 | } 1540 | { 1541 | auto container_result = from_array (customers) >> container (); 1542 | auto begin = container_result.begin (); 1543 | auto end = container_result.end (); 1544 | 1545 | TEST_ASSERT (true, (begin != end)); 1546 | TEST_ASSERT (false, (begin == end)); 1547 | 1548 | auto c = *begin; 1549 | 1550 | TEST_ASSERT (1U, c.id); 1551 | TEST_ASSERT (1U, begin->id); 1552 | TEST_ASSERT (1U, (*begin).id); 1553 | 1554 | 1555 | } 1556 | } 1557 | 1558 | void test_where () 1559 | { 1560 | using namespace cpplinq; 1561 | 1562 | TEST_PRELUDE (); 1563 | 1564 | { 1565 | auto c = from (empty_vector) >> where (is_even) >> count (); 1566 | TEST_ASSERT (0U, c); 1567 | } 1568 | 1569 | { 1570 | auto c = from_array (ints) >> where (is_even) >> count (); 1571 | TEST_ASSERT (even_count_of_ints, c); 1572 | } 1573 | 1574 | { 1575 | auto v = from_array (ints) >> where (is_even) >> first_or_default (); 1576 | TEST_ASSERT (4, v); 1577 | } 1578 | } 1579 | 1580 | void test_ref () 1581 | { 1582 | using namespace cpplinq; 1583 | 1584 | TEST_PRELUDE (); 1585 | 1586 | { 1587 | std::vector> ref_result = 1588 | from (empty_vector) 1589 | >> ref () 1590 | >> to_vector () 1591 | ; 1592 | TEST_ASSERT (0U, ref_result.size ()); 1593 | } 1594 | 1595 | { 1596 | std::vector> ref_result = 1597 | from_array (customers) 1598 | >> ref () 1599 | >> to_vector () 1600 | ; 1601 | 1602 | auto index = 0U; 1603 | for (auto customer : ref_result) 1604 | { 1605 | if (!TEST_ASSERT (customers[index].id, customer.get ().id)) 1606 | { 1607 | PRINT_INDEX (index); 1608 | } 1609 | 1610 | ++index; 1611 | } 1612 | 1613 | TEST_ASSERT (count_of_customers, ref_result.size ()); 1614 | } 1615 | } 1616 | 1617 | void test_select () 1618 | { 1619 | using namespace cpplinq; 1620 | 1621 | TEST_PRELUDE (); 1622 | 1623 | { 1624 | std::vector select_result = from (empty_vector) >> select ([](int i){return 1.0*i;}) >> to_vector (); 1625 | TEST_ASSERT (0U, select_result.size ()); 1626 | } 1627 | 1628 | { 1629 | std::vector select_result = 1630 | from_array (customers) 1631 | >> select ([](customer const & c){return c.id;}) 1632 | >> to_vector () 1633 | ; 1634 | 1635 | std::size_t index = 0U; 1636 | for (auto sz : select_result) 1637 | { 1638 | if (!TEST_ASSERT (customers[index].id, sz)) 1639 | { 1640 | PRINT_INDEX (index); 1641 | } 1642 | 1643 | ++index; 1644 | } 1645 | 1646 | TEST_ASSERT (count_of_customers, select_result.size ()); 1647 | } 1648 | 1649 | } 1650 | 1651 | void test_join () 1652 | { 1653 | using namespace cpplinq; 1654 | 1655 | TEST_PRELUDE (); 1656 | 1657 | { 1658 | auto cs = empty (); 1659 | auto cas = empty (); 1660 | 1661 | auto join_result = cs 1662 | >> join ( 1663 | cas 1664 | , [](customer const & c) {return c.id;} 1665 | , [](customer_address const & ca) {return ca.customer_id;} 1666 | , [](customer const & c, customer_address const & ca) {return std::make_pair (c, ca);} 1667 | ) 1668 | >> to_vector () 1669 | ; 1670 | 1671 | TEST_ASSERT (0U, join_result.size ()); 1672 | } 1673 | { 1674 | auto cas = empty (); 1675 | 1676 | auto join_result = from_array (customers) 1677 | >> join ( 1678 | cas 1679 | , [](customer const & c) {return c.id;} 1680 | , [](customer_address const & ca) {return ca.customer_id;} 1681 | , [](customer const & c, customer_address const & ca) {return std::make_pair (c, ca);} 1682 | ) 1683 | >> to_vector () 1684 | ; 1685 | 1686 | TEST_ASSERT (0U, join_result.size ()); 1687 | } 1688 | { 1689 | auto cs = empty (); 1690 | 1691 | auto join_result = cs 1692 | >> join ( 1693 | from_array (customer_addresses) 1694 | , [](customer const & c) {return c.id;} 1695 | , [](customer_address const & ca) {return ca.customer_id;} 1696 | , [](customer const & c, customer_address const & ca) {return std::make_pair (c, ca);} 1697 | ) 1698 | >> to_vector () 1699 | ; 1700 | 1701 | TEST_ASSERT (0U, join_result.size ()); 1702 | } 1703 | { 1704 | auto join_result = from_array (customers) 1705 | >> join ( 1706 | from_array (customer_addresses) 1707 | , [](customer const & c) {return c.id;} 1708 | , [](customer_address const & ca) {return ca.customer_id;} 1709 | , [](customer const & c, customer_address const & ca) {return std::make_pair (c, ca);} 1710 | ) 1711 | >> to_vector () 1712 | ; 1713 | 1714 | if (TEST_ASSERT (3U, join_result.size ())) 1715 | { 1716 | { 1717 | auto result = join_result[0]; 1718 | TEST_ASSERT (1U, result.first.id); 1719 | TEST_ASSERT (1U, result.second.id); 1720 | } 1721 | { 1722 | auto result = join_result[1]; 1723 | TEST_ASSERT (4U, result.first.id); 1724 | TEST_ASSERT (2U, result.second.id); 1725 | } 1726 | { 1727 | auto result = join_result[2]; 1728 | TEST_ASSERT (4U, result.first.id); 1729 | TEST_ASSERT (3U, result.second.id); 1730 | } 1731 | } 1732 | } 1733 | } 1734 | 1735 | void test_select_many () 1736 | { 1737 | using namespace cpplinq; 1738 | 1739 | TEST_PRELUDE (); 1740 | 1741 | { 1742 | std::vector select_many_result = 1743 | from_iterators (customers, customers) 1744 | >> select_many ([](customer const & c){return from (c.last_name);}) 1745 | >> to_vector () 1746 | ; 1747 | 1748 | TEST_ASSERT (0U, select_many_result.size ()); 1749 | } 1750 | { 1751 | std::vector expected; 1752 | for (auto customer : customers) 1753 | { 1754 | expected.insert ( 1755 | expected.end () 1756 | , customer.last_name.begin () 1757 | , customer.last_name.end () 1758 | ); 1759 | } 1760 | 1761 | std::vector select_many_result = 1762 | from_array (customers) 1763 | >> select_many ([](customer const & c){return from (c.last_name);}) 1764 | >> to_vector () 1765 | ; 1766 | 1767 | if (TEST_ASSERT (expected.size (), select_many_result.size ())) 1768 | { 1769 | for (std::size_t index = 0U; index < expected.size (); ++index) 1770 | { 1771 | if (!TEST_ASSERT (expected[index], select_many_result[index])) 1772 | { 1773 | PRINT_INDEX (index); 1774 | } 1775 | } 1776 | } 1777 | } 1778 | 1779 | } 1780 | 1781 | void test_orderby () 1782 | { 1783 | using namespace cpplinq; 1784 | 1785 | TEST_PRELUDE (); 1786 | 1787 | { 1788 | auto c = from (empty_vector) >> orderby_ascending ([](int i){return i;}) >> count (); 1789 | TEST_ASSERT (0U, c); 1790 | } 1791 | 1792 | { 1793 | auto c = 1794 | from (empty_customers) 1795 | >> orderby_ascending ([] (customer const & c) {return c.last_name;}) 1796 | >> thenby_ascending ([] (customer const & c) {return c.first_name;}) 1797 | >> count () 1798 | ; 1799 | TEST_ASSERT (0U, c); 1800 | } 1801 | 1802 | const std::size_t test_set_size = 7; 1803 | 1804 | auto verify = [=]( 1805 | std::size_t expected[test_set_size] 1806 | , std::vector const & sequence 1807 | ) 1808 | { 1809 | auto sz = sequence.size (); 1810 | if (TEST_ASSERT (test_set_size, sz)) 1811 | { 1812 | std::size_t index = 0U; 1813 | for (auto c : sequence) 1814 | { 1815 | if (!TEST_ASSERT (expected[index], c.id)) 1816 | { 1817 | PRINT_INDEX (index); 1818 | } 1819 | 1820 | ++index; 1821 | } 1822 | 1823 | } 1824 | }; 1825 | 1826 | { 1827 | std::size_t expected[] = 1828 | { 1829 | 1, 1830 | 2, 1831 | 3, 1832 | 4, 1833 | 11, 1834 | 12, 1835 | 21, 1836 | }; 1837 | 1838 | auto sequence = 1839 | from_array (customers) 1840 | >> orderby_ascending ([] (customer const & c) {return c.id;}) 1841 | >> to_vector () 1842 | ; 1843 | 1844 | verify (expected, sequence); 1845 | } 1846 | { 1847 | std::size_t expected[] = 1848 | { 1849 | 21, 1850 | 12, 1851 | 11, 1852 | 4, 1853 | 3, 1854 | 2, 1855 | 1, 1856 | }; 1857 | 1858 | auto sequence = 1859 | from_array (customers) 1860 | >> orderby_descending ([] (customer const & c) {return c.id;}) 1861 | >> to_vector () 1862 | ; 1863 | 1864 | verify (expected, sequence); 1865 | } 1866 | { 1867 | std::size_t expected[] = 1868 | { 1869 | 11, 1870 | 12, 1871 | 1, 1872 | 21, 1873 | 2, 1874 | 3, 1875 | 4, 1876 | }; 1877 | 1878 | auto sequence = 1879 | from_array (customers) 1880 | >> orderby_ascending ([] (customer const & c) {return c.last_name;}) 1881 | >> thenby_ascending ([] (customer const & c) {return c.first_name;}) 1882 | >> to_vector () 1883 | ; 1884 | 1885 | verify (expected, sequence); 1886 | } 1887 | { 1888 | std::size_t expected[] = 1889 | { 1890 | 4, 1891 | 3, 1892 | 2, 1893 | 21, 1894 | 1, 1895 | 12, 1896 | 11, 1897 | }; 1898 | 1899 | auto sequence = 1900 | from_array (customers) 1901 | >> orderby_descending ([] (customer const & c) {return c.last_name;}) 1902 | >> thenby_descending ([] (customer const & c) {return c.first_name;}) 1903 | >> to_vector () 1904 | ; 1905 | 1906 | verify (expected, sequence); 1907 | } 1908 | { 1909 | std::size_t expected[] = 1910 | { 1911 | 11, 1912 | 12, 1913 | 21, 1914 | 1, 1915 | 2, 1916 | 3, 1917 | 4, 1918 | }; 1919 | 1920 | auto sequence = 1921 | from_array (customers) 1922 | >> orderby ([] (customer const & c) {return c.last_name;}, true) 1923 | >> thenby ([] (customer const & c) {return c.first_name;}, false) 1924 | >> to_vector () 1925 | ; 1926 | 1927 | verify (expected, sequence); 1928 | } 1929 | } 1930 | 1931 | void test_reverse () 1932 | { 1933 | using namespace cpplinq; 1934 | 1935 | TEST_PRELUDE (); 1936 | 1937 | // reverse an empty range 1938 | { 1939 | auto result = empty() >> reverse () >> to_vector (); 1940 | TEST_ASSERT (0U, result.size ()); 1941 | } 1942 | 1943 | // reverse an empty range 1944 | { 1945 | auto result = from (empty_vector) >> reverse () >> to_vector (); 1946 | TEST_ASSERT (0U, result.size ()); 1947 | } 1948 | 1949 | // reverse a non-empty range 1950 | { 1951 | int expected[] = {9,8,7,6,5,4,3,2,1,0}; 1952 | auto expected_size = get_array_size (expected); 1953 | 1954 | auto result = range (0, 10) >> reverse () >> to_vector (); 1955 | TEST_ASSERT (expected_size, result.size ()); 1956 | 1957 | for (auto i = 0U; i < expected_size && i < result.size (); ++i) 1958 | { 1959 | TEST_ASSERT (expected[i], result[i]); 1960 | } 1961 | } 1962 | 1963 | // code coverage test 1964 | { 1965 | auto q = empty() >> reverse (); 1966 | 1967 | TEST_ASSERT (false, q.next ()); 1968 | TEST_ASSERT (false, q.next ()); 1969 | } 1970 | } 1971 | 1972 | void test_skip () 1973 | { 1974 | using namespace cpplinq; 1975 | 1976 | TEST_PRELUDE (); 1977 | 1978 | { 1979 | auto q = from (empty_vector) >> skip (5); 1980 | std::size_t index = 0U; 1981 | 1982 | while (q.next ()) 1983 | { 1984 | test_int_at (index, q.front ()); 1985 | ++index; 1986 | } 1987 | TEST_ASSERT (0U, index); 1988 | } 1989 | { 1990 | auto q = from_array (ints) >> skip (5); 1991 | 1992 | auto index = 5U; 1993 | 1994 | while (q.next ()) 1995 | { 1996 | test_int_at (index, q.front ()); 1997 | ++index; 1998 | } 1999 | TEST_ASSERT (count_of_ints, index); 2000 | } 2001 | 2002 | // code coverage test 2003 | { 2004 | auto q = from (empty_vector) >> skip (1); 2005 | 2006 | TEST_ASSERT (false, q.next ()); 2007 | TEST_ASSERT (false, q.next ()); 2008 | } 2009 | } 2010 | 2011 | void test_skip_while () 2012 | { 2013 | using namespace cpplinq; 2014 | 2015 | TEST_PRELUDE (); 2016 | 2017 | { 2018 | auto q = from (empty_vector) >> skip_while (smaller_than_five); 2019 | std::size_t index = 0U; 2020 | 2021 | while (q.next ()) 2022 | { 2023 | test_int_at (index, q.front ()); 2024 | ++index; 2025 | } 2026 | TEST_ASSERT (0U, index); 2027 | } 2028 | { 2029 | auto q = from_array (ints) >> skip_while (smaller_than_five); 2030 | std::size_t index = 4U; 2031 | 2032 | while (q.next ()) 2033 | { 2034 | test_int_at (index, q.front ()); 2035 | ++index; 2036 | } 2037 | TEST_ASSERT (count_of_ints, index); 2038 | } 2039 | } 2040 | 2041 | void test_take () 2042 | { 2043 | using namespace cpplinq; 2044 | 2045 | TEST_PRELUDE (); 2046 | 2047 | { 2048 | auto q = from (empty_vector) >> take (5); 2049 | std::size_t index = 0U; 2050 | 2051 | while (q.next ()) 2052 | { 2053 | test_int_at (index, q.front ()); 2054 | ++index; 2055 | } 2056 | TEST_ASSERT (0U, index); 2057 | } 2058 | { 2059 | auto q = from_array (ints) >> take (5); 2060 | 2061 | std::size_t index = 0U; 2062 | 2063 | while (q.next ()) 2064 | { 2065 | test_int_at (index, q.front ()); 2066 | ++index; 2067 | } 2068 | TEST_ASSERT (5U, index); 2069 | } 2070 | { 2071 | auto c = from_array (ints) >> take (5) >> count (); 2072 | 2073 | TEST_ASSERT (5U, c); 2074 | } 2075 | } 2076 | 2077 | void test_take_while () 2078 | { 2079 | using namespace cpplinq; 2080 | 2081 | TEST_PRELUDE (); 2082 | 2083 | { 2084 | auto q = from (empty_vector) >> take_while (smaller_than_five); 2085 | std::size_t index = 0U; 2086 | 2087 | while (q.next ()) 2088 | { 2089 | test_int_at (index, q.front ()); 2090 | ++index; 2091 | } 2092 | TEST_ASSERT (0U, index); 2093 | } 2094 | 2095 | { 2096 | auto q = from_array (ints) >> take_while (smaller_than_five); 2097 | std::size_t index = 0U; 2098 | 2099 | while (q.next ()) 2100 | { 2101 | test_int_at (index, q.front ()); 2102 | ++index; 2103 | } 2104 | TEST_ASSERT (4U, index); 2105 | } 2106 | 2107 | // code coverage test 2108 | { 2109 | auto q = from_array (ints) >> take_while ([] (int i) {return i < 0;}); 2110 | 2111 | TEST_ASSERT (false, q.next ()); 2112 | TEST_ASSERT (false, q.next ()); 2113 | } 2114 | } 2115 | 2116 | void test_contains () 2117 | { 2118 | using namespace cpplinq; 2119 | 2120 | TEST_PRELUDE (); 2121 | 2122 | { 2123 | bool result = from (empty_vector) >> contains (1); 2124 | TEST_ASSERT (false, result); 2125 | } 2126 | 2127 | { 2128 | bool result = from_array (ints) >> contains (1); 2129 | TEST_ASSERT (true, result); 2130 | } 2131 | 2132 | { 2133 | bool result = 2134 | from (empty_customers) 2135 | >> contains ( 2136 | customer (1, "Bill", "Gates"), 2137 | [](customer const& c1, customer const& c2) {return c1.id == c2.id;}); 2138 | 2139 | TEST_ASSERT (false, result); 2140 | } 2141 | 2142 | { 2143 | bool result = 2144 | from_array (customers) 2145 | >> contains ( 2146 | customer (1, "Bill", "Gates"), 2147 | [](customer const& c1, customer const& c2) {return c1.id == c2.id;}); 2148 | 2149 | TEST_ASSERT (true, result); 2150 | } 2151 | 2152 | { 2153 | bool result = 2154 | from_array (customers) 2155 | >> contains ( 2156 | customer (42, "Bill", "Gates"), 2157 | [](customer const& c1, customer const& c2) {return c1.id == c2.id;}); 2158 | 2159 | TEST_ASSERT (false, result); 2160 | } 2161 | } 2162 | 2163 | void test_element_at_or_default () 2164 | { 2165 | using namespace cpplinq; 2166 | 2167 | TEST_PRELUDE (); 2168 | 2169 | { 2170 | auto result = from (empty_vector) >> element_at_or_default (0); 2171 | TEST_ASSERT (0, result); 2172 | } 2173 | 2174 | { 2175 | auto result = from (empty_vector) >> element_at_or_default (1); 2176 | TEST_ASSERT (0, result); 2177 | } 2178 | 2179 | { 2180 | auto result = from_array (ints) >> element_at_or_default (0); 2181 | TEST_ASSERT (3, result); 2182 | } 2183 | 2184 | { 2185 | auto result = from_array (ints) >> element_at_or_default (1); 2186 | TEST_ASSERT (1, result); 2187 | } 2188 | 2189 | { 2190 | auto result = from_array (ints) >> element_at_or_default (count_of_ints-1); 2191 | TEST_ASSERT (5, result); 2192 | } 2193 | 2194 | { 2195 | auto result = from_array (ints) >> element_at_or_default (count_of_ints); 2196 | TEST_ASSERT (0, result); 2197 | } 2198 | 2199 | } 2200 | 2201 | void test_aggregate () 2202 | { 2203 | using namespace cpplinq; 2204 | 2205 | TEST_PRELUDE (); 2206 | 2207 | { 2208 | int sum_result = from (empty_vector) >> aggregate (0, sum_aggregator); 2209 | TEST_ASSERT (0, sum_result); 2210 | } 2211 | 2212 | { 2213 | int sum_of_simple_ints = std::accumulate (simple_ints, simple_ints + count_of_simple_ints, 0); 2214 | int sum_result = from_array (simple_ints) >> aggregate (0, sum_aggregator); 2215 | TEST_ASSERT (sum_of_simple_ints, sum_result); 2216 | } 2217 | 2218 | { 2219 | int prod_of_simple_ints = std::accumulate (simple_ints, simple_ints + count_of_simple_ints, 1, mul_aggregator); 2220 | int sum_result = from_array (simple_ints) >> aggregate (1, mul_aggregator); 2221 | TEST_ASSERT (prod_of_simple_ints, sum_result); 2222 | } 2223 | 2224 | { 2225 | auto sum_result = from (empty_vector) >> aggregate (0, sum_aggregator, to_string); 2226 | TEST_ASSERT ("0", sum_result); 2227 | } 2228 | 2229 | { 2230 | auto sum_of_simple_ints = to_string (std::accumulate (simple_ints, simple_ints + count_of_simple_ints, 0)); 2231 | auto sum_result = from_array (simple_ints) >> aggregate (0, sum_aggregator, to_string); 2232 | TEST_ASSERT (sum_of_simple_ints, sum_result); 2233 | } 2234 | 2235 | { 2236 | auto prod_of_simple_ints = to_string (std::accumulate (simple_ints, simple_ints + count_of_simple_ints, 1, mul_aggregator)); 2237 | auto sum_result = from_array (simple_ints) >> aggregate (1, mul_aggregator, to_string); 2238 | TEST_ASSERT (prod_of_simple_ints, sum_result); 2239 | } 2240 | } 2241 | 2242 | void test_distinct () 2243 | { 2244 | using namespace cpplinq; 2245 | 2246 | TEST_PRELUDE (); 2247 | 2248 | { 2249 | auto d = from (empty_vector) >> distinct () >> to_vector (); 2250 | TEST_ASSERT (0U, d.size ()); 2251 | } 2252 | 2253 | { 2254 | int expected[] = {5,4,3,2,1}; 2255 | auto expected_size = get_array_size (expected); 2256 | 2257 | auto result = from_array (set1) >> distinct () >> to_vector (); 2258 | auto result_size = result.size (); 2259 | 2260 | TEST_ASSERT (expected_size, result_size); 2261 | for (auto i = 0U; i < expected_size && i < result_size; ++i) 2262 | { 2263 | TEST_ASSERT (expected[i], result[i]); 2264 | } 2265 | } 2266 | 2267 | { 2268 | auto d = from_array (customers_set1) >> distinct () >> to_vector (); 2269 | TEST_ASSERT (4U, d.size ()); 2270 | } 2271 | 2272 | } 2273 | 2274 | void test_union_with () 2275 | { 2276 | using namespace cpplinq; 2277 | 2278 | TEST_PRELUDE (); 2279 | 2280 | // union of two empty ranges 2281 | { 2282 | auto result = from (empty_vector) >> union_with (from (empty_vector) ) >> to_vector (); 2283 | TEST_ASSERT (0U, result.size ()); 2284 | } 2285 | 2286 | // union of an empty range with a non-empty range 2287 | { 2288 | auto result = empty() >> union_with (range (0, 10) ) >> to_vector (); 2289 | TEST_ASSERT (10U, result.size ()); 2290 | for (auto i = 0U; i < 10 && i < result.size (); ++i) 2291 | { 2292 | TEST_ASSERT (static_cast (i), result[i]); 2293 | } 2294 | } 2295 | 2296 | // union of an empty range with a non-empty range 2297 | { 2298 | int expected[] = {5,4,3,2,1}; 2299 | auto expected_size = get_array_size (expected); 2300 | auto result = from (empty_vector) >> union_with ( from_array (set1) ) >> to_vector (); 2301 | TEST_ASSERT (expected_size, result.size ()); 2302 | 2303 | for (auto i = 0U; i < result.size () && i < expected_size; ++i) 2304 | { 2305 | TEST_ASSERT (expected[i], result[i]); 2306 | } 2307 | } 2308 | 2309 | // union of a non-empty range with an empty range 2310 | { 2311 | auto result = range (0, 10) >> union_with (empty() ) >> to_vector (); 2312 | TEST_ASSERT (10U, result.size ()); 2313 | for (auto i = 0U; i < 10 && i < result.size (); ++i) 2314 | { 2315 | TEST_ASSERT (static_cast (i), result[i]); 2316 | } 2317 | } 2318 | 2319 | // union of a non-empty range with an empty range 2320 | { 2321 | int expected[] = {5,4,3,2,1}; 2322 | auto expected_size = get_array_size (expected); 2323 | auto result = from_array (set1) >> union_with (from (empty_vector)) >> to_vector (); 2324 | TEST_ASSERT (expected_size, result.size ()); 2325 | for (auto i = 0U; i < expected_size && i < result.size (); ++i) 2326 | { 2327 | TEST_ASSERT (expected[i], result[i]); 2328 | } 2329 | } 2330 | 2331 | // union of two non-empty ranges 2332 | { 2333 | int expected[] = {5,4,3,2,1,9,8,6,7}; 2334 | auto expected_size = get_array_size (expected); 2335 | 2336 | auto result = from_array (set1) >> union_with (from_array (set2)) >> to_vector (); 2337 | auto result_size = result.size (); 2338 | 2339 | TEST_ASSERT (expected_size, result_size); 2340 | for (auto i = 0U; i < expected_size && i < result_size; ++i) 2341 | { 2342 | TEST_ASSERT (expected[i], result[i]); 2343 | } 2344 | } 2345 | 2346 | // union of range with duplicates with itself 2347 | { 2348 | auto result = from_array (ints) >> union_with (from_array (ints)) >> to_vector (); 2349 | auto result_size = result.size (); 2350 | 2351 | TEST_ASSERT (9U, result_size); 2352 | } 2353 | } 2354 | 2355 | void test_intersect_with () 2356 | { 2357 | using namespace cpplinq; 2358 | 2359 | TEST_PRELUDE (); 2360 | 2361 | // intersection of two empty ranges 2362 | { 2363 | auto result = from (empty_vector) >> intersect_with (from (empty_vector) ) >> to_vector (); 2364 | TEST_ASSERT (0U, result.size ()); 2365 | } 2366 | 2367 | // intersection of an empty range with a non-empty range 2368 | { 2369 | auto result = empty() >> intersect_with (range (0, 10) ) >> to_vector (); 2370 | TEST_ASSERT (0U, result.size ()); 2371 | } 2372 | 2373 | // intersection of an empty range with a non-empty range 2374 | { 2375 | auto result = from (empty_vector) >> intersect_with (from_array (set1)) >> to_vector (); 2376 | TEST_ASSERT (0U, result.size ()); 2377 | } 2378 | 2379 | // intersection of a non-empty range with an empty range 2380 | { 2381 | auto result = range (0, 10) >> intersect_with (empty() ) >> to_vector (); 2382 | TEST_ASSERT (0U, result.size ()); 2383 | } 2384 | 2385 | // intersection of a non-empty range with an empty range 2386 | { 2387 | auto result = from_array (set1) >> intersect_with (from (empty_vector)) >> to_vector (); 2388 | TEST_ASSERT (0U, result.size ()); 2389 | } 2390 | 2391 | // intersection of two non-empty ranges 2392 | { 2393 | int expected[] = {5,4,1}; 2394 | auto expected_size = get_array_size (expected); 2395 | 2396 | auto result = from_array (set1) >> intersect_with (from_array (set2)) >> to_vector (); 2397 | auto result_size = result.size (); 2398 | 2399 | TEST_ASSERT (expected_size, result_size); 2400 | for (auto i = 0U; i < expected_size && i < result_size; ++i) 2401 | { 2402 | TEST_ASSERT (expected[i], result[i]); 2403 | } 2404 | } 2405 | 2406 | // intersection of two non-empty ranges 2407 | { 2408 | int expected[] = {4,5,1}; 2409 | auto expected_size = get_array_size (expected); 2410 | 2411 | auto result = from_array (set2) >> intersect_with (from_array (set1)) >> to_vector (); 2412 | auto result_size = result.size (); 2413 | 2414 | TEST_ASSERT (expected_size, result_size); 2415 | for (auto i = 0U; i < expected_size && i < result_size; ++i) 2416 | { 2417 | TEST_ASSERT (expected[i], result[i]); 2418 | } 2419 | } 2420 | 2421 | // intersection of non-empty range with duplicates with itself 2422 | { 2423 | int numbers [] = {3,1,4,1,5,9,2,6,5,4}; 2424 | int expected [] = {3,1,4,5,9,2,6}; 2425 | auto expected_size = get_array_size (expected); 2426 | 2427 | auto result = from_array (numbers) >> intersect_with (from_array (numbers)) >> to_vector (); 2428 | auto result_size = result.size (); 2429 | 2430 | TEST_ASSERT (expected_size, result_size); 2431 | for (auto i = 0U; i < expected_size && i < result_size; ++i) 2432 | { 2433 | TEST_ASSERT (expected[i], result[i]); 2434 | } 2435 | } 2436 | 2437 | // code coverage test 2438 | { 2439 | auto q = from (empty_vector) >> intersect_with (from (empty_vector) ); 2440 | 2441 | TEST_ASSERT (false, q.next ()); 2442 | TEST_ASSERT (false, q.next ()); 2443 | } 2444 | } 2445 | 2446 | void test_except () 2447 | { 2448 | using namespace cpplinq; 2449 | 2450 | TEST_PRELUDE (); 2451 | 2452 | // difference of two empty ranges 2453 | { 2454 | auto result = from (empty_vector) >> except (from (empty_vector)) >> to_vector (); 2455 | TEST_ASSERT (0U, result.size ()); 2456 | } 2457 | 2458 | // difference of an empty range with a non-empty range 2459 | { 2460 | auto result = empty() >> except (range (0, 10)) >> to_vector (); 2461 | TEST_ASSERT (0U, result.size ()); 2462 | } 2463 | 2464 | // difference of an empty range with a non-empty range 2465 | { 2466 | auto result = from (empty_vector) >> except (from_array (set1)) >> to_vector (); 2467 | TEST_ASSERT (0U, result.size ()); 2468 | } 2469 | 2470 | // difference of a non-empty range with an empty range 2471 | { 2472 | auto result = range (0, 10) >> except (empty()) >> to_vector (); 2473 | TEST_ASSERT (10U, result.size ()); 2474 | for (auto i = 0U; i < 10 && i < result.size (); ++i) 2475 | { 2476 | TEST_ASSERT (static_cast (i), result[i]); 2477 | } 2478 | } 2479 | 2480 | // difference of a non-empty range with an empty range 2481 | { 2482 | int expected[] = {5,4,3,2,1}; 2483 | auto expected_size = get_array_size (expected); 2484 | 2485 | auto result = from_array (set1) >> except (from (empty_vector)) >> to_vector (); 2486 | TEST_ASSERT (expected_size, result.size ()); 2487 | for (auto i = 0U; i < expected_size && i < result.size (); ++i) 2488 | { 2489 | TEST_ASSERT (expected[i], result[i]); 2490 | } 2491 | } 2492 | 2493 | // difference of two non-empty ranges 2494 | { 2495 | int expected[] = {3,2}; 2496 | auto expected_size = get_array_size (expected); 2497 | 2498 | auto result = from_array (set1) >> except (from_array (set2)) >> to_vector (); 2499 | auto result_size = result.size (); 2500 | 2501 | TEST_ASSERT (expected_size, result_size); 2502 | for (auto i = 0U; i < expected_size && i < result_size; ++i) 2503 | { 2504 | TEST_ASSERT (expected[i], result[i]); 2505 | } 2506 | } 2507 | 2508 | // difference of two non-empty ranges 2509 | { 2510 | int expected[] = {9,8,6,7}; 2511 | auto expected_size = get_array_size (expected); 2512 | 2513 | auto result = from_array (set2) >> except (from_array (set1)) >> to_vector (); 2514 | auto result_size = result.size (); 2515 | 2516 | TEST_ASSERT (expected_size, result_size); 2517 | for (auto i = 0U; i < expected_size && i < result_size; ++i) 2518 | { 2519 | TEST_ASSERT (expected[i], result[i]); 2520 | } 2521 | } 2522 | 2523 | // difference of non-empty range with duplicates with itself 2524 | { 2525 | int numbers [] = {3,1,4,1,5,9,2,6,5,4}; 2526 | 2527 | auto result = from_array (numbers) >> except (from_array (numbers)) >> to_vector (); 2528 | auto result_size = result.size (); 2529 | 2530 | TEST_ASSERT (0U, result_size); 2531 | } 2532 | 2533 | // difference of non-empty range with duplicates with empty set 2534 | { 2535 | auto result = from_array (ints) >> except (from (empty_vector)) >> to_vector (); 2536 | auto result_size = result.size (); 2537 | 2538 | TEST_ASSERT (9U, result_size); 2539 | } 2540 | } 2541 | 2542 | void test_concat () 2543 | { 2544 | using namespace cpplinq; 2545 | 2546 | TEST_PRELUDE (); 2547 | 2548 | // concat two empty ranges 2549 | { 2550 | auto result = empty() >> concat (empty()) >> to_vector (); 2551 | TEST_ASSERT (0U, result.size ()); 2552 | } 2553 | 2554 | // concat two empty ranges 2555 | { 2556 | auto result = from (empty_vector) >> concat (empty()) >> to_vector (); 2557 | TEST_ASSERT (0U, result.size ()); 2558 | } 2559 | 2560 | // concat an empty range with a non empty range 2561 | { 2562 | auto expected = range (0,10); 2563 | auto expected_result = expected >> to_vector (); 2564 | auto result = empty() >> concat (expected) >> to_vector (); 2565 | TEST_ASSERT (expected_result.size (), result.size ()); 2566 | for (auto i = 0U; i < expected_result.size () && i < result.size ();++i) 2567 | { 2568 | TEST_ASSERT (expected_result[i], result[i]); 2569 | } 2570 | } 2571 | 2572 | // concat an empty range with a non empty range 2573 | { 2574 | auto result = empty() >> concat (from_array (ints)) >> to_vector (); 2575 | TEST_ASSERT (count_of_ints, result.size ()); 2576 | for (auto i = 0U; i < count_of_ints && i < result.size ();++i) 2577 | { 2578 | TEST_ASSERT (ints[i], result[i]); 2579 | } 2580 | } 2581 | 2582 | // concat a non empty range with an empty range 2583 | { 2584 | auto expected = range (0,10); 2585 | auto expected_result = expected >> to_vector (); 2586 | auto result = expected >> concat (empty()) >> to_vector (); 2587 | TEST_ASSERT (expected_result.size (), result.size ()); 2588 | for (auto i = 0U; i < expected_result.size () && i < result.size ();++i) 2589 | { 2590 | TEST_ASSERT (expected_result[i], result[i]); 2591 | } 2592 | } 2593 | 2594 | // concat a non empty range with an empty range 2595 | { 2596 | auto result = from_array (ints) >> concat (empty()) >> to_vector (); 2597 | TEST_ASSERT (count_of_ints, result.size ()); 2598 | for (auto i = 0U; i < count_of_ints && i < result.size ();++i) 2599 | { 2600 | TEST_ASSERT (ints[i], result[i]); 2601 | } 2602 | } 2603 | 2604 | // concat two non-empty ranges 2605 | { 2606 | int set1[] = {0,1,2,3,4,5}; 2607 | int set2[] = {6,7,8,9}; 2608 | auto result = from_array (set1) >> concat (from_array (set2)) >> to_vector (); 2609 | TEST_ASSERT (10U, result.size ()); 2610 | for (auto i = 0U; i < 10 && i < result.size (); ++i) 2611 | { 2612 | TEST_ASSERT (static_cast (i), result[i]); 2613 | } 2614 | } 2615 | 2616 | // code coverage test 2617 | { 2618 | auto q = empty() >> concat (empty()); 2619 | 2620 | TEST_ASSERT (false, q.next ()); 2621 | TEST_ASSERT (false, q.next ()); 2622 | } 2623 | } 2624 | 2625 | void test_sequence_equal () 2626 | { 2627 | using namespace cpplinq; 2628 | 2629 | TEST_PRELUDE (); 2630 | 2631 | // test two empty sequences 2632 | { 2633 | auto result = empty() >> sequence_equal (empty()); 2634 | TEST_ASSERT (true, result); 2635 | } 2636 | 2637 | // test two empty sequences 2638 | { 2639 | auto result = from (empty_vector) >> sequence_equal (empty()); 2640 | TEST_ASSERT (true, result); 2641 | } 2642 | 2643 | // test empty sequence with non-empty sequence 2644 | { 2645 | auto result = empty() >> sequence_equal (range (0,10)); 2646 | TEST_ASSERT (false, result); 2647 | } 2648 | 2649 | // test empty sequence with non-empty sequence 2650 | { 2651 | auto result = from (empty_vector) >> sequence_equal (from_array (ints)); 2652 | TEST_ASSERT (false, result); 2653 | } 2654 | 2655 | // test non-empty sequence with empty sequence 2656 | { 2657 | auto result = range (0, 10) >> sequence_equal (empty()); 2658 | TEST_ASSERT (false, result); 2659 | } 2660 | 2661 | // test non-empty sequence with empty sequence 2662 | { 2663 | auto result = from_array (ints) >> sequence_equal (from (empty_vector)); 2664 | TEST_ASSERT (false, result); 2665 | } 2666 | 2667 | // test non-empty inequal sequences 2668 | { 2669 | auto result = range (0,5) >> sequence_equal (range (0,4)); 2670 | TEST_ASSERT (false, result); 2671 | } 2672 | 2673 | // test non-empty inequal sequences 2674 | { 2675 | auto result = from_array (set1) >> sequence_equal (from_array (set2)); 2676 | TEST_ASSERT (false, result); 2677 | } 2678 | 2679 | // test non-empty equal sequences 2680 | { 2681 | auto result = from_array (ints) >> sequence_equal (from_array (ints)); 2682 | TEST_ASSERT (true, result); 2683 | } 2684 | 2685 | // test non-empty equal sequences 2686 | { 2687 | auto result = range (0,10) >> sequence_equal (range (0,10)); 2688 | TEST_ASSERT (true, result); 2689 | } 2690 | 2691 | // test against self 2692 | { 2693 | auto seq = from_array (ints); 2694 | auto result = seq >> sequence_equal (seq); 2695 | TEST_ASSERT (true, result); 2696 | } 2697 | 2698 | auto comparer = [](customer const& c1, customer const& c2) 2699 | {return c1.first_name == c2.first_name && c1.last_name == c2.last_name;}; 2700 | 2701 | customer customers1[] = { 2702 | customer (1 , "Bill" , "Gates" ), 2703 | customer (2 , "Steve" , "Jobs" ), 2704 | customer (3 , "Richard" , "Stallman"), 2705 | }; 2706 | 2707 | customer customers2[] = { 2708 | customer (11 , "Bill" , "Gates" ), 2709 | customer (12 , "Steve" , "Jobs" ), 2710 | customer (13 , "Richard" , "Stallman"), 2711 | }; 2712 | 2713 | customer customers3[] = { 2714 | customer (1 , "Bill" , "Gates" ), 2715 | customer (2 , "Steve" , "Jobs" ), 2716 | customer (3 , "Steve" , "Ballmer" ), 2717 | }; 2718 | 2719 | // test empty with comparer 2720 | { 2721 | auto result = empty() >> sequence_equal (empty(), comparer); 2722 | TEST_ASSERT (true, result); 2723 | } 2724 | 2725 | // test empty with non-empty with comparer 2726 | { 2727 | auto result = from (empty_customers) >> sequence_equal (from_array (customers), comparer); 2728 | TEST_ASSERT (false, result); 2729 | } 2730 | 2731 | // test non-empty with empty with comparer 2732 | { 2733 | auto result = from_array (customers) >> sequence_equal (from (empty_customers), comparer); 2734 | TEST_ASSERT (false, result); 2735 | } 2736 | 2737 | // test two equal non-empty sequences with comparer 2738 | { 2739 | auto result = from_array (customers1) >> sequence_equal (from_array (customers2), comparer); 2740 | TEST_ASSERT (true, result); 2741 | } 2742 | 2743 | // test two inequal non-empty sequences with comparer 2744 | { 2745 | auto result = from_array (customers1) >> sequence_equal (from_array (customers3), comparer); 2746 | TEST_ASSERT (false, result); 2747 | } 2748 | 2749 | // test against self with comparer 2750 | { 2751 | auto seq = from_array (customers1); 2752 | auto result = seq >> sequence_equal (seq, comparer); 2753 | TEST_ASSERT (true, result); 2754 | } 2755 | } 2756 | 2757 | void test_pairwise () 2758 | { 2759 | using namespace cpplinq; 2760 | 2761 | TEST_PRELUDE (); 2762 | 2763 | { 2764 | auto pairwise_result = 2765 | from (empty_vector) 2766 | >> pairwise () 2767 | >> to_vector () 2768 | ; 2769 | TEST_ASSERT (0U, pairwise_result.size ()); 2770 | } 2771 | 2772 | { 2773 | int single_element_vector[] = {1}; 2774 | auto pairwise_result = 2775 | from_array (single_element_vector) 2776 | >> pairwise () 2777 | >> to_vector () 2778 | ; 2779 | TEST_ASSERT (0U, pairwise_result.size ()); 2780 | } 2781 | 2782 | { 2783 | auto pairwise_result = 2784 | from_array (simple_ints) 2785 | >> pairwise () 2786 | >> to_vector () 2787 | ; 2788 | TEST_ASSERT (count_of_simple_ints-1, pairwise_result.size ()); 2789 | for (std::size_t i=0; i < pairwise_result.size (); ++i) 2790 | { 2791 | TEST_ASSERT (simple_ints[i], pairwise_result[i].first); 2792 | TEST_ASSERT (simple_ints[i+1], pairwise_result[i].second); 2793 | } 2794 | } 2795 | } 2796 | 2797 | void test_zip_with () 2798 | { 2799 | using namespace cpplinq; 2800 | TEST_PRELUDE (); 2801 | 2802 | { 2803 | auto zip_width_result = 2804 | from (empty_vector) 2805 | >> zip_with (from (empty_vector)) 2806 | >> to_vector () 2807 | ; 2808 | TEST_ASSERT (0U, zip_width_result.size ()); 2809 | } 2810 | 2811 | { 2812 | auto zip_width_result = 2813 | from (empty_vector) 2814 | >> zip_with (from_array (simple_ints)) 2815 | >> to_vector () 2816 | ; 2817 | TEST_ASSERT (0U, zip_width_result.size ()); 2818 | } 2819 | 2820 | { 2821 | auto zip_width_result = 2822 | from_array (simple_ints) 2823 | >> zip_with (from (empty_vector)) 2824 | >> to_vector () 2825 | ; 2826 | TEST_ASSERT (0U, zip_width_result.size ()); 2827 | } 2828 | 2829 | { 2830 | auto zip_width_result = 2831 | from_array (simple_ints) 2832 | >> zip_with (from_array (simple_ints)) 2833 | >> to_vector () 2834 | ; 2835 | TEST_ASSERT (count_of_simple_ints, zip_width_result.size ()); 2836 | for (std::size_t i=0; i> zip_with (from_array (simple_ints)) 2848 | >> to_vector () 2849 | ; 2850 | TEST_ASSERT (expected_size, zip_width_result.size ()); 2851 | for (std::size_t i=0; i> zip_with (from_array (ints)) 2863 | >> to_vector () 2864 | ; 2865 | TEST_ASSERT (expected_size, zip_width_result.size ()); 2866 | for (std::size_t i=0; i> zip_with(from_array(simple_ints)) 2878 | >> to_vector(); 2879 | 2880 | auto expected_size = get_array_size(pairrange); 2881 | TEST_ASSERT(expected_size, zip_width_result.size()); 2882 | for (std::size_t i=0; i 2891 | long long execute_testruns ( 2892 | std::size_t test_runs 2893 | , TPredicate predicate 2894 | ) 2895 | { 2896 | auto then = std::chrono::high_resolution_clock::now (); 2897 | 2898 | for (auto test_run = 0U; test_run < test_runs; ++test_run) 2899 | { 2900 | predicate (); 2901 | } 2902 | 2903 | auto now = std::chrono::high_resolution_clock::now (); 2904 | 2905 | auto diff = now - then; 2906 | 2907 | auto diff_in_ms = std::chrono::duration_cast(diff).count (); 2908 | 2909 | return diff_in_ms; 2910 | } 2911 | 2912 | void test_performance_range_sum () 2913 | { 2914 | using namespace cpplinq; 2915 | 2916 | TEST_PRELUDE (); 2917 | 2918 | int const test_repeat = 80000 ; 2919 | int const test_size = 20000 ; 2920 | auto expected_complete_sum = 0 ; 2921 | auto result_complete_sum = 0 ; 2922 | 2923 | auto expected = execute_testruns ( 2924 | test_repeat 2925 | , [&] () 2926 | { 2927 | auto set_sum = 0; 2928 | for (auto iter = 0; iter < test_size; ++iter) 2929 | { 2930 | set_sum += iter; 2931 | } 2932 | expected_complete_sum += set_sum; 2933 | } 2934 | ); 2935 | 2936 | auto result = execute_testruns ( 2937 | test_repeat 2938 | , [&] () 2939 | { 2940 | auto set_sum = 2941 | range(0, test_size) 2942 | >> sum () 2943 | ; 2944 | result_complete_sum += set_sum; 2945 | } 2946 | ); 2947 | 2948 | TEST_ASSERT (expected_complete_sum, result_complete_sum); 2949 | 2950 | auto ratio_limit = 3.0; 2951 | auto ratio = ((double)expected)/result; 2952 | TEST_ASSERT (true, (ratio > 1/ratio_limit && ratio < ratio_limit)); 2953 | printf ( 2954 | "Performance numbers for simple sum over numbers, expected:%lld, result:%lld, ratio_limit:%f, ratio:%f\n" 2955 | , expected 2956 | , result 2957 | , ratio_limit 2958 | , ratio 2959 | ); 2960 | } 2961 | 2962 | void test_performance_sum () 2963 | { 2964 | using namespace cpplinq; 2965 | 2966 | TEST_PRELUDE (); 2967 | 2968 | int const test_repeat = 80000 ; 2969 | int const test_size = 20000 ; 2970 | auto expected_complete_sum = 0 ; 2971 | auto result_complete_sum = 0 ; 2972 | 2973 | srand (19740531); 2974 | 2975 | auto test_set = 2976 | range (0, test_size) 2977 | >> select ([] (int i){return rand ();}) 2978 | >> to_vector (test_size) 2979 | ; 2980 | 2981 | auto expected = execute_testruns ( 2982 | test_repeat 2983 | , [&] () 2984 | { 2985 | auto set_sum = 0; 2986 | for (auto v : test_set) 2987 | { 2988 | set_sum += v; 2989 | } 2990 | expected_complete_sum += set_sum; 2991 | } 2992 | ); 2993 | 2994 | auto result = execute_testruns ( 2995 | test_repeat 2996 | , [&] () 2997 | { 2998 | auto set_sum = 2999 | from (test_set) 3000 | >> sum () 3001 | ; 3002 | result_complete_sum += set_sum; 3003 | } 3004 | ); 3005 | 3006 | TEST_ASSERT (expected_complete_sum, result_complete_sum); 3007 | 3008 | auto ratio_limit = 2.0; 3009 | auto ratio = ((double)expected)/result; 3010 | TEST_ASSERT (true, (ratio > 1/ratio_limit && ratio < ratio_limit)); 3011 | printf ( 3012 | "Performance numbers for simple sum over numbers, expected:%lld, result:%lld, ratio_limit:%f, ratio:%f\n" 3013 | , expected 3014 | , result 3015 | , ratio_limit 3016 | , ratio 3017 | ); 3018 | } 3019 | 3020 | bool is_prime (int i) 3021 | { 3022 | if (i < 2) 3023 | { 3024 | return false; 3025 | } 3026 | else if (i == 2) 3027 | { 3028 | return true; 3029 | } 3030 | else 3031 | { 3032 | auto r = std::ceil (std::sqrt (i)); 3033 | 3034 | for (auto iter = 2; iter <= r; ++iter) 3035 | { 3036 | if (i % iter == 0) 3037 | { 3038 | return false; 3039 | } 3040 | } 3041 | 3042 | return true; 3043 | } 3044 | } 3045 | 3046 | void test_performance_is_prime () 3047 | { 3048 | using namespace cpplinq; 3049 | 3050 | TEST_PRELUDE (); 3051 | 3052 | #if _DEBUG 3053 | int const test_repeat = 25 ; 3054 | #else 3055 | int const test_repeat = 100 ; 3056 | #endif 3057 | int const test_size = 10000 ; 3058 | 3059 | auto expected_complete_sum = 0 ; 3060 | auto result_complete_sum = 0 ; 3061 | 3062 | auto expected = execute_testruns ( 3063 | test_repeat 3064 | , [&] () 3065 | { 3066 | auto iter = 3; 3067 | auto count = 0; 3068 | auto expected_sum= 0; 3069 | while (count < test_size) 3070 | { 3071 | if (is_prime (iter)) 3072 | { 3073 | expected_sum += iter; 3074 | ++count; 3075 | } 3076 | iter += 2; 3077 | } 3078 | expected_complete_sum += expected_sum; 3079 | } 3080 | ); 3081 | 3082 | auto result = execute_testruns ( 3083 | test_repeat 3084 | , [&] () 3085 | { 3086 | result_complete_sum += 3087 | range (1, INT_MAX) 3088 | >> select ([] (int i) {return 2*i + 1;}) 3089 | >> where (is_prime) 3090 | >> take (test_size) 3091 | >> sum () 3092 | ; 3093 | } 3094 | ); 3095 | 3096 | TEST_ASSERT (expected_complete_sum, result_complete_sum); 3097 | 3098 | auto ratio_limit = 1.25; 3099 | auto ratio = ((double)expected)/result; 3100 | TEST_ASSERT (true, (ratio > 1/ratio_limit && ratio < ratio_limit)); 3101 | printf ( 3102 | "Performance numbers for computing primes, expected:%lld, result:%lld, ratio_limit:%f, ratio:%f\n" 3103 | , expected 3104 | , result 3105 | , ratio_limit 3106 | , ratio 3107 | ); 3108 | } 3109 | 3110 | bool run_all_tests (bool run_perfomance_tests) 3111 | { 3112 | // ------------------------------------------------------------------------- 3113 | test_opt (); 3114 | test_lookup (); 3115 | test_from (); 3116 | test_range (); 3117 | test_repeat (); 3118 | test_empty (); 3119 | test_singleton (); 3120 | test_generate (); 3121 | test_set (); 3122 | test_count (); 3123 | test_any (); 3124 | test_first (); 3125 | test_first_or_default (); 3126 | test_last_or_default (); 3127 | test_sum (); 3128 | test_avg (); 3129 | test_max (); 3130 | test_min (); 3131 | test_concatenate (); 3132 | test_all (); 3133 | test_for_each (); 3134 | test_to_vector (); 3135 | test_to_map (); 3136 | test_to_lookup (); 3137 | test_to_list (); 3138 | test_container (); 3139 | test_where (); 3140 | test_ref (); 3141 | test_select (); 3142 | test_select_many (); 3143 | test_join (); 3144 | test_orderby (); 3145 | test_reverse (); 3146 | test_take (); 3147 | test_skip (); 3148 | test_take_while (); 3149 | test_skip_while (); 3150 | test_contains (); 3151 | test_element_at_or_default (); 3152 | test_aggregate (); 3153 | test_distinct (); 3154 | test_union_with (); 3155 | test_intersect_with (); 3156 | test_except (); 3157 | test_concat (); 3158 | test_sequence_equal (); 3159 | test_pairwise (); 3160 | test_zip_with (); 3161 | // ------------------------------------------------------------------------- 3162 | if (run_perfomance_tests) 3163 | { 3164 | #ifdef _MSC_VER 3165 | // In order to make performance number more predictable 3166 | SetPriorityClass (GetCurrentProcess (), HIGH_PRIORITY_CLASS); 3167 | #endif 3168 | test_performance_range_sum (); 3169 | test_performance_sum (); 3170 | test_performance_is_prime (); 3171 | } 3172 | // ------------------------------------------------------------------------- 3173 | if (errors == 0) 3174 | { 3175 | printf ("PASS\n"); 3176 | } 3177 | else 3178 | { 3179 | printf ("FAIL\n"); 3180 | } 3181 | // ------------------------------------------------------------------------- 3182 | return errors > 0; 3183 | // ------------------------------------------------------------------------- 3184 | } 3185 | } 3186 | // ---------------------------------------------------------------------------------------------- 3187 | --------------------------------------------------------------------------------