• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
linq_last_(Cursor c,onepass_cursor_tag)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
linq_last_(Cursor c,forward_cursor_tag)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
linq_last_(Cursor c,random_access_cursor_tag)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
linq_last_or_default_(Cursor c,onepass_cursor_tag)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
linq_last_or_default_(Cursor c,forward_cursor_tag)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
linq_last_or_default_(Cursor c,random_access_cursor_tag)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