sled/3party/cpplinq/linq_last.hpp

86 lines
2.2 KiB
C++
Raw Normal View History

2024-03-14 20:50:17 +08:00
// 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 <class Cursor>
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 <class Cursor>
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 <class Cursor>
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 <class Cursor>
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 <class Cursor>
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 <class Cursor>
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