Advertisement
Inverness

Preliminary LINQ

Jun 17th, 2012
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.57 KB | None | 0 0
  1. #ifndef _LINQ_HPP
  2. #define _LINQ_HPP
  3.  
  4. #include <exception>
  5. #include <algorithm>
  6. #include <iterator>
  7. #include <type_traits>
  8.  
  9. namespace linq
  10. {
  11.  
  12. class invalid_query: public std::exception
  13. {
  14. };
  15.  
  16. // if T::value_type is not valid, this can be specialized to
  17. // select the value type
  18. template <typename Iterable>
  19. struct get_value_type
  20. {
  21.     typedef typename Iterable::value_type type;
  22. };
  23.  
  24. // Determine if an iterator supports random access
  25. template <typename Iterator>
  26. struct is_random_access
  27. {
  28.     typename std::is_same<typename std::iterator_traits<Iterator>::iterator_category, std::random_access_iterator_tag> type;
  29. };
  30.  
  31. // Get the type of T's iterator
  32. template <typename Container>
  33. struct iterator_type
  34. {
  35.     typedef decltype(begin(Container())) type;
  36. };
  37.  
  38. // simple example
  39. template <typename T>
  40. bool always_true(T const& t)
  41. {
  42.     return true;
  43. }
  44.  
  45. template <typename Container, typename Value>
  46. class query_impl
  47. {
  48. public:
  49.     typedef typename query_impl<Container, Value> this_type;
  50.     typedef typename Container container_type;
  51.     typedef typename Value value_type;
  52.     typedef unsigned long long size_type;
  53.     typedef typename iterator_type<Container>::type iterator;
  54.     typedef typename iterator_type<const Container>::type const_iterator;
  55.     typedef is_random_access<iterator> is_random_access;
  56.  
  57.     query_impl(container_type& t):
  58.         _target(t)
  59.     {
  60.     }
  61.  
  62.     const_iterator begin() const
  63.     {
  64.         return std::begin(_target);
  65.     }
  66.  
  67.     iterator begin()
  68.     {
  69.         return std::begin(_target);
  70.     }
  71.  
  72.     const_iterator cbegin() const
  73.     {
  74.         return std::begin(_target);
  75.     }
  76.  
  77.     const_iterator end() const
  78.     {
  79.         return std::end(_target);
  80.     }
  81.  
  82.     iterator end()
  83.     {
  84.         return std::end(_target);
  85.     }
  86.  
  87.     const_iterator cend() const
  88.     {
  89.         return std::end(_target);
  90.     }
  91.  
  92.     container_type& target()
  93.     {
  94.         return _target;
  95.     }
  96.  
  97.     container_type const& target() const
  98.     {
  99.         return _target;
  100.     }
  101.  
  102.     size_type count() const
  103.     {
  104.         return std::distance(std::begin(_target), std::end(_target));
  105.     }
  106.  
  107.     template <typename Func>
  108.     bool all(Func func) const
  109.     {
  110.         for (auto it = std::begin(_target); it != std::end(_target); it++)
  111.         {
  112.             if (!func(*it))
  113.                 return false;
  114.         }
  115.         return true;
  116.     }
  117.  
  118.     value_type sum() const
  119.     {
  120.         value_type v = value_type();
  121.         for (auto it = std::begin(_target); it != std::end(_target); it++)
  122.             v += *it;
  123.         return v;
  124.     }
  125.  
  126.     value_type& first() const
  127.     {
  128.         if (std::begin(_target) == std::end(_target))
  129.             throw invalid_query();
  130.         return *std::begin(_target);
  131.     }
  132.  
  133.     value_type& first(value_type& default_) const
  134.     {
  135.         if (std::begin(_target) == std::end(_target))
  136.             return default_;
  137.         return *std::begin(_target);
  138.     }
  139.  
  140.     value_type& last() const
  141.     {
  142.         if (std::begin(_target) == std::end(_target))
  143.             throw invalid_query();
  144.         return *(--std::end(_target));
  145.     }
  146.  
  147.     value_type& last(value_type& default_) const
  148.     {
  149.         if (std::begin(_target) == std::end(_target))
  150.             return default_;
  151.         return *(--std::end(_target));
  152.     }
  153.  
  154.     template <typename Pred>
  155.     this_type& where(Pred predicate)
  156.     {
  157.         for (auto it = std::begin(_target); it != std::end(_target);)
  158.         {
  159.             if (predicate(*it))
  160.             {
  161.                 it++;
  162.                 continue;
  163.             }
  164.             it = _target.erase(it);
  165.             if (it == std::end(_target))
  166.                 break;
  167.         }
  168.         return *this;
  169.     }
  170.  
  171.     this_type& skip(size_type count)
  172.     {
  173.         if (count > INT_MAX)
  174.             throw std::overflow_error("count > INT_MAX");
  175.         _target.erase(std::begin(_target), std::next(std::begin(_target), (int)count));
  176.         return *this;
  177.     }
  178.  
  179.     template <typename Func>
  180.     this_type& select(Func func)
  181.     {
  182.         std::for_each(std::begin(_target), std::end(_target), func);
  183.         return *this;
  184.     }
  185.  
  186. protected:
  187.     container_type& _target;
  188. };
  189.  
  190. // A type of query that copies the contents of the provided SourceContainer into a new ResultContainer
  191. // which is used as the target for queries.
  192. template <typename SourceContainer, typename Value, typename ResultContainer = std::vector<Value>>
  193. class query_impl_copy: public query_impl<ResultContainer, Value>
  194. {
  195. public:
  196.     typedef SourceContainer source_container_type;
  197.  
  198.     query_impl_copy(source_container_type& t):
  199.         query_impl(_result),
  200.         _result(t.begin(), t.end())
  201.     {
  202.     }
  203.  
  204. private:
  205.  
  206.     container_type _result;
  207. };
  208.  
  209. // creates new query object and determines value type using get_value_type<Container>
  210. template <typename Container>
  211. query_impl<Container, typename get_value_type<Container>::type> query(Container& t)
  212. {
  213.     return query_impl<Container, get_value_type<Container>::type>(t);
  214. }
  215.  
  216. // explicit value type specification
  217. template <typename Container, typename Value>
  218. query_impl<Container, Value> query(Container& t)
  219. {
  220.     return query_impl<Container, Value>(t);
  221. }
  222.  
  223. // Create new copy query, which copies the data of the provided container to serve as the target
  224. // for queries.
  225. template <typename SourceContainer>
  226. query_impl_copy<SourceContainer, typename get_value_type<SourceContainer>::type> querycopy(SourceContainer& t)
  227. {
  228.     return query_impl_copy<SourceContainer, get_value_type<SourceContainer>::type>(t);
  229. }
  230.  
  231. } // namespace linq
  232.  
  233. #endif // _LINQ_HPP
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement