Skip to content

Commit

Permalink
container_helpers: is_sorted_and_unique 3x fewer comparison ops (Ukoe…
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeffro authored Oct 24, 2023
1 parent b6c52f0 commit f5915c6
Showing 1 changed file with 16 additions and 11 deletions.
27 changes: 16 additions & 11 deletions src/common/container_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,12 @@ inline auto compare_func(ComparisonOpT comparison_op_func)
}
/// test if a container is sorted and unique according to a comparison criteria (defaults to operator<)
/// NOTE: ComparisonOpT must establish 'strict weak ordering' https://en.cppreference.com/w/cpp/named_req/Compare
/// NOTE: T::const_iterator must satisfy LegacyForwardIterator https://en.cppreference.com/w/cpp/named_req/ForwardIterator
template <typename T, typename ComparisonOpT = std::less<typename T::value_type>>
bool is_sorted_and_unique(const T &container, ComparisonOpT comparison_op = ComparisonOpT{})
{
using ValueT = typename T::value_type;
using ConstIt = typename T::const_iterator;
static_assert(
std::is_same<
bool,
Expand All @@ -90,17 +92,20 @@ bool is_sorted_and_unique(const T &container, ComparisonOpT comparison_op = Comp
"invalid callable - expected callable in form bool(ValueT, ValueT)"
);

if (!std::is_sorted(container.begin(), container.end(), comparison_op))
return false;

if (std::adjacent_find(container.begin(),
container.end(),
[comparison_op = std::move(comparison_op)](const ValueT &a, const ValueT &b) -> bool
{
return !comparison_op(a, b) && !comparison_op(b, a);
})
!= container.end())
return false;
const ConstIt end = container.cend();

ConstIt it_a = container.cbegin();
if (it_a == end)
return true;

ConstIt it_b = it_a;
it_b++;

for (; it_b != end; it_a = it_b++)
{
if (!comparison_op(*it_a, *it_b))
return false;
}

return true;
}
Expand Down

0 comments on commit f5915c6

Please sign in to comment.