// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. #if !defined(CPPLINQ_LINQ_LAST_HPP) #define CPPLINQ_LINQ_LAST_HPP #pragma once namespace cpplinq { template typename Cursor::element_type linq_last_(Cursor c, onepass_cursor_tag) { if (c.empty()) { throw std::logic_error("last() out of bounds"); } typename Cursor::element_type elem = c.get(); for(;;) { c.inc(); if (c.empty()) break; elem = c.get(); } return elem; } // TODO: bidirectional iterator in constant time template typename Cursor::reference_type linq_last_(Cursor c, forward_cursor_tag) { if (c.empty()) { throw std::logic_error("last() out of bounds"); } Cursor best = c; for(;;) { c.inc(); if (c.empty()) break; best = c; } return best.get(); } template typename Cursor::reference_type linq_last_(Cursor c, random_access_cursor_tag) { if (c.empty()) { throw std::logic_error("last() out of bounds"); } c.skip(c.size()-1); return c.get(); } template typename Cursor::element_type linq_last_or_default_(Cursor c, onepass_cursor_tag) { typename Cursor::element_type elem; while(!c.empty()) { elem = c.get(); c.inc(); } return elem; } template typename Cursor::element_type linq_last_or_default_(Cursor c, forward_cursor_tag) { if (c.empty()) { throw std::logic_error("last() out of bounds"); } Cursor best = c; for(;;) { c.inc(); if (c.empty()) break; best = c; } return best.get(); } template typename Cursor::element_type linq_last_or_default_(Cursor c, random_access_cursor_tag) { if (c.empty()) { return typename Cursor::element_type(); } c.skip(c.size()-1); return c.get(); } } #endif // CPPLINQ_LINQ_LAST_HPP