Home | History | Annotate | Download | only in cpplinq
      1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
      2 
      3 #if !defined(CPPLINQ_LINQ_LAST_HPP)
      4 #define CPPLINQ_LINQ_LAST_HPP
      5 #pragma once
      6 
      7 namespace cpplinq {
      8 
      9     template <class Cursor>
     10     typename Cursor::element_type
     11         linq_last_(Cursor c, onepass_cursor_tag)
     12     {
     13         if (c.empty()) { throw std::logic_error("last() out of bounds"); }
     14         typename Cursor::element_type elem = c.get();
     15         for(;;) {
     16             c.inc();
     17             if (c.empty()) break;
     18             elem = c.get();
     19         }
     20         return elem;
     21     }
     22 
     23     // TODO: bidirectional iterator in constant time
     24 
     25     template <class Cursor>
     26     typename Cursor::reference_type
     27         linq_last_(Cursor c, forward_cursor_tag)
     28     {
     29         if (c.empty()) { throw std::logic_error("last() out of bounds"); }
     30         Cursor best = c;
     31         for(;;) {
     32             c.inc();
     33             if (c.empty()) break;
     34             best = c;
     35         }
     36         return best.get();
     37     }
     38 
     39     template <class Cursor>
     40     typename Cursor::reference_type
     41         linq_last_(Cursor c, random_access_cursor_tag)
     42     {
     43         if (c.empty()) { throw std::logic_error("last() out of bounds"); }
     44         c.skip(c.size()-1);
     45         return c.get();
     46     }
     47 
     48     template <class Cursor>
     49     typename Cursor::element_type
     50         linq_last_or_default_(Cursor c, onepass_cursor_tag)
     51     {
     52         typename Cursor::element_type elem;
     53         while(!c.empty()) {
     54             elem = c.get();
     55             c.inc();
     56         }
     57         return elem;
     58     }
     59 
     60     template <class Cursor>
     61     typename Cursor::element_type
     62         linq_last_or_default_(Cursor c, forward_cursor_tag)
     63     {
     64         if (c.empty()) { throw std::logic_error("last() out of bounds"); }
     65         Cursor best = c;
     66         for(;;) {
     67             c.inc();
     68             if (c.empty()) break;
     69             best = c;
     70         }
     71         return best.get();
     72     }
     73 
     74     template <class Cursor>
     75     typename Cursor::element_type
     76         linq_last_or_default_(Cursor c, random_access_cursor_tag)
     77     {
     78         if (c.empty()) { return typename Cursor::element_type(); }
     79         c.skip(c.size()-1);
     80         return c.get();
     81     }
     82 
     83 }
     84 
     85 #endif // CPPLINQ_LINQ_LAST_HPP
     86