fork download
  1. // List comprehension in C++11 in form of SQL-like syntax
  2. // Example code from http://v...content-available-to-author-only...y.info/cpp11-writing-list-comprehension-in-form-of-sql/
  3. // Written by Victor Laskin
  4.  
  5. #include <iostream>
  6. #include <functional>
  7. #include <vector>
  8. #include <future>
  9. #include <algorithm>
  10. using namespace std;
  11.  
  12. // This is for converting lambda / pointer into correponding std::function<>
  13.  
  14. template <typename Fun>
  15. struct fn_is_ptr: std::integral_constant<bool, std::is_pointer<Fun>::value
  16. && std::is_function< typename std::remove_pointer<Fun>::type>::value>
  17. {};
  18.  
  19. template <typename ReturnType, typename... Args, class = typename std::enable_if<fn_is_ptr< ReturnType(*)(Args...) >::value>::type>
  20. std::function<ReturnType(Args...)> to_fn (ReturnType (*fp)(Args...))
  21. {
  22. return std::function<ReturnType(Args...)>(fp);
  23. }
  24.  
  25.  
  26. template <typename Function>
  27. struct function_traits : public function_traits<decltype(&Function::operator())>
  28. {};
  29.  
  30. template <typename ClassType, typename ReturnType, typename... Args>
  31. struct function_traits<ReturnType(ClassType::*)(Args...) const>
  32. {
  33. typedef ReturnType (*pointer)(Args...);
  34. typedef std::function<ReturnType(Args...)> function;
  35. };
  36.  
  37. template <typename Function, class = typename std::enable_if<!fn_is_ptr<Function>::value>::type>
  38. typename function_traits<Function>::function to_fn(Function& lambda)
  39. {
  40. return typename function_traits<Function>::function(lambda);
  41. }
  42.  
  43. template <typename Function, class = typename std::enable_if<!fn_is_ptr<Function>::value>::type>
  44. typename function_traits<Function>::function to_fn(const Function& lambda)
  45. {
  46. return typename function_traits<Function>::function(lambda);
  47. }
  48.  
  49. // Range of natural integers
  50. class Naturals
  51. {
  52. int min;
  53. int max;
  54. public:
  55. Naturals() : min(1),max(1000) {}
  56. Naturals(int min, int max) : min(min),max(max) {}
  57. int at(int i) const { return i + min; } ;
  58. int size() const { return max - min + 1; } ;
  59.  
  60. class Iterator {
  61. int position;
  62. public:
  63. Iterator(int _position):position(_position) {}
  64. int& operator*() { return position; }
  65. Iterator& operator++() { ++position; return *this; }
  66. bool operator!=(const Iterator& it) const { return position != it.position; }
  67. };
  68.  
  69. Iterator begin() const { return { min }; }
  70. Iterator end() const { return { max }; }
  71. };
  72.  
  73.  
  74. // Additional options
  75.  
  76. class SelectOption {
  77. private:
  78. virtual bool imPolymorphic() { return true; }
  79. };
  80.  
  81. class SelectOptionLimit : public SelectOption {
  82. public:
  83. int limit;
  84. SelectOptionLimit(int limit) : limit(limit) {}
  85. };
  86.  
  87. class SelectOptionSort : public SelectOption {};
  88.  
  89. class SelectOptionDistict : public SelectOption {};
  90.  
  91. class SelectContinuation : public SelectOption {
  92. public:
  93. vector<int> indexes;
  94. SelectContinuation(){}
  95. template <typename... Args>
  96. SelectContinuation(Args... args) : indexes{ args... } { }
  97. };
  98.  
  99.  
  100. /// Main iterations
  101.  
  102. template <typename Src, typename... Args>
  103. inline typename std::enable_if< std::is_object<decltype(std::declval<Src>().begin()) >::value, Src&&>::type
  104. getSource(Src && src, Args&&... args) {
  105. return std::forward<Src&&>(src);
  106. }
  107.  
  108.  
  109. template <typename F, typename... Args, typename FRes = decltype(std::declval<F>()(std::declval<Args>()...))>
  110. inline typename std::enable_if<std::is_object< decltype(std::declval<F>()(std::declval<Args>()...)) >::value, FRes >::type
  111. getSource(F && f, Args&&... args)
  112. {
  113. return std::forward<FRes>(f(std::forward<Args>(args)...));
  114. }
  115.  
  116.  
  117. template<std::size_t I = 0, typename FuncT, typename... Tp, typename... Args>
  118. inline typename std::enable_if<I == sizeof...(Tp), bool>::type
  119. for_each_in_sources(const std::tuple<Tp...> &, FuncT& f, Args&... args)
  120. {
  121. return f(args...);
  122. }
  123.  
  124. template<std::size_t I = 0, typename FuncT, typename... Tp, typename... Args>
  125. inline typename std::enable_if< I < sizeof...(Tp), bool>::type
  126. for_each_in_sources(const std::tuple<Tp...>& t, FuncT& f, Args&... args)
  127. {
  128. bool isFinished;
  129. auto&& src = getSource(std::get<I>(t), args...);
  130. for(auto& element : src)
  131. {
  132. isFinished = for_each_in_sources<I + 1, FuncT, Tp...>(t, f, args..., element);
  133. if (isFinished) break;
  134. }
  135. return isFinished;
  136. }
  137.  
  138.  
  139. template<std::size_t I = 0, typename FuncT, typename... Tp, typename... Args>
  140. inline typename std::enable_if<I == sizeof...(Tp), bool>::type
  141. for_each_in_sources_indexed(const std::tuple<Tp...> &, FuncT& f, vector<int>& indexes, Args&&... args)
  142. {
  143. return f(args...);
  144. }
  145.  
  146.  
  147. template<std::size_t I = 0, typename FuncT, typename... Tp, typename... Args>
  148. inline typename std::enable_if< I < sizeof...(Tp), bool>::type
  149. for_each_in_sources_indexed(const std::tuple<Tp...>& t, FuncT& f, vector<int>& indexes, Args&&... args)
  150. {
  151. bool isFinished;
  152. auto&& src = getSource(std::get<I>(t), args...);
  153. int size = src.size();
  154. int i = indexes[I];
  155. if (I != 0) if (i >= size) i = 0;
  156. if (i >= size) return false;
  157. for (; i < size; i++)
  158. {
  159. isFinished = for_each_in_sources_indexed<I + 1, FuncT, Tp...>(t, f, indexes, args..., src.at(i));
  160. if (isFinished) break;
  161. }
  162. indexes[I] = ++i;
  163. return isFinished;
  164. }
  165.  
  166. template <typename R, typename... Args, typename... Sources, typename... Options>
  167. vector<R> select(const std::function<R(Args...)>& f, ///< output expression
  168. const std::tuple<Sources...>& sources, ///< list of sources
  169. const std::function<bool(Args...)>& filter, ///< composition of filters
  170. const Options&... options ///< other options and flags
  171. )
  172. {
  173. int limit = -1;
  174. bool isDistinct = false;
  175. bool isSorted = false;
  176.  
  177. vector<int>* indexes = nullptr;
  178.  
  179. for_each_argument([&](const SelectOption& option){
  180. if (auto opt = dynamic_cast<const SelectOptionLimit*>(&option)) { limit = opt->limit; };
  181. if (dynamic_cast<const SelectOptionSort*>(&option)) { isSorted = true; };
  182. if (dynamic_cast<const SelectOptionDistict*>(&option)) { isDistinct = true; };
  183. if (auto opt = dynamic_cast<const SelectContinuation*>(&option)) { indexes = &( (const_cast<SelectContinuation*>(opt))->indexes ); };
  184. }, (options)...);
  185.  
  186. vector<R> result;
  187. int count = 0;
  188. auto process = [&](const Args&... args){
  189. if (filter(args...))
  190. {
  191. result.push_back(f(args...));
  192. count++;
  193. }
  194. return (count == limit); // isFinished
  195. };
  196.  
  197. if (indexes == nullptr)
  198. for_each_in_sources(sources, process);
  199. else
  200. {
  201. if (indexes->size() == 0)
  202. {
  203. indexes->resize(std::tuple_size<std::tuple<Sources...>>::value);
  204. std::fill(indexes->begin(), indexes->end(), 0);
  205. }
  206.  
  207. for_each_in_sources_indexed(sources, process, *indexes);
  208. }
  209.  
  210. // sort results
  211. if ((isDistinct) || (isSorted))
  212. std::sort(result.begin(), result.end());
  213.  
  214. // remove duplicates
  215. if (isDistinct)
  216. {
  217. auto last = std::unique(result.begin(), result.end());
  218. result.erase(last, result.end());
  219. }
  220.  
  221. return result;
  222. }
  223.  
  224. template <typename R, typename... Args, typename... Sources, typename... Options>
  225. inline vector<R> select(std::function<R(Args...)> f,
  226. const std::tuple<Sources...>& sources,
  227. const Options&... options)
  228. {
  229. return select(f, sources, to_fn([](Args... args){ return true; }), options...);
  230. }
  231.  
  232. // EVIL WAY
  233.  
  234. #define SELECT(X) select(to_fn(X),
  235. //#define FROM(...) std::forward_as_tuple(__VA_ARGS__)
  236. #define FROM(...) std::make_tuple(__VA_ARGS__)
  237. #define WHERE(...) ,to_fn(__VA_ARGS__)
  238. #define SORT ,SelectOptionSort()
  239. #define DISTINCT ,SelectOptionDistict()
  240. #define LIMIT(X) ,SelectOptionLimit(X))
  241. #define NOLIMIT LIMIT(-1)
  242.  
  243.  
  244. template <typename R, typename... Args, typename... Sources, typename... Options>
  245. std::function<vector<R>()> select_lazy(const std::function<R(Args...)>& f, ///< output expression
  246. const std::tuple<Sources...>& sources, ///< list of sources
  247. const std::function<bool(Args...)>& filter, ///< composition of filters
  248. const Options&... options ///< other options and flags
  249. )
  250. {
  251. return to_fn([=](){ return select(f, sources, filter, options...); });
  252. }
  253.  
  254.  
  255. template <typename R, typename... Args, typename... Sources, typename... Options>
  256. std::function<vector<R>(const SelectContinuation& job)> select_concurrent(
  257. const std::function<R(Args...)>& f, ///< output expression
  258. const std::tuple<Sources...>& sources, ///< list of sources
  259. const std::function<bool(Args...)>& filter, ///< composition of filters
  260. const Options&... options ///< other options and flags
  261. )
  262. {
  263. return to_fn([=](const SelectContinuation& job){ return select(f, sources, filter, job, options...); });
  264. }
  265.  
  266. #define CONCURRENTSELECT(X) select_concurrent(to_fn(X),
  267. #define LAZYSELECT(X) select_lazy(to_fn(X),
  268. #define LAZY(X) ,(X)
  269.  
  270.  
  271. /// Call function for each argument
  272. template <class F, class... Args>
  273. void for_each_argument(F f, Args&&... args) {
  274. (void)(int[]){(f(forward<Args>(args)), 0)...};
  275. }
  276.  
  277. int main() {
  278.  
  279. // EXAMPLES
  280.  
  281. auto print = [](vector<int>& list){ cout << "List: "; for (int x : list) cout << x << " "; cout << endl;};
  282.  
  283. cout << "10 naturals" << endl;
  284. auto result = SELECT([](int x){ return x; }) FROM(Naturals()) LIMIT(10);
  285. print(result);
  286.  
  287. cout << "Distinct test" << endl;
  288. result = SELECT([](int x, int y){ return x+y; }) FROM(Naturals(), Naturals())
  289. WHERE([](int x, int y){ return (x*x + y*y < 25); }) DISTINCT LIMIT(10);
  290. print(result);
  291.  
  292. cout << "Intersection" << endl;
  293. vector<int> ints = {11,2,1,5,6,7};
  294. vector<int> ints2 = {3,4,5,7,8,11};
  295.  
  296. result = SELECT([](int x, int y){ return x; })
  297. FROM(ints, ints2)
  298. WHERE([](int x, int y){ return (x == y); }) SORT NOLIMIT;
  299. print(result);
  300.  
  301. // Simple map operation as list comprehension
  302. cout << "Map" << endl;
  303. result = SELECT([](int x){ return x + 5; }) FROM(ints) NOLIMIT;
  304. print(result);
  305.  
  306. cout << "Pythagorean Triplets" << endl;
  307. SelectContinuation state;
  308.  
  309. auto lazypyth = LAZYSELECT([&](int x, int y, int z){ return make_tuple(z,y,x); })
  310. FROM(Naturals(1,100000000),
  311. [](int x){ return Naturals(1,x); },
  312. [](int x,int y){ return Naturals(1,y); })
  313. WHERE([&](int x, int y, int z){ return x*x == y*y + z*z; })
  314. LAZY(state) LIMIT(5);
  315.  
  316. auto pyth = lazypyth();
  317. cout << "Part1:" << endl;
  318. for (auto line: pyth) cout << " -> " << get<0>(line) << " " << get<1>(line) << " " << get<2>(line) << endl;
  319. pyth = lazypyth();
  320. cout << "Part2:" << endl;
  321. for (auto line: pyth) cout << " -> " << get<0>(line) << " " << get<1>(line) << " " << get<2>(line) << endl;
  322.  
  323. return 0;
  324. }
Success #stdin #stdout 0s 3296KB
stdin
Standard input is empty
stdout
10 naturals
List: 1 2 3 4 5 6 7 8 9 10 
Distinct test
List: 2 3 4 5 6 
Intersection
List: 5 7 11 
Map
List: 16 7 6 10 11 12 
Pythagorean Triplets
Part1:
 -> 3 4 5
 -> 6 8 10
 -> 5 12 13
 -> 9 12 15
 -> 8 15 17
Part2:
 -> 12 16 20
 -> 15 20 25
 -> 7 24 25
 -> 10 24 26
 -> 20 21 29