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