近值排序
report from :https://codereview.stackexchange.com/questions/48470/std-lib-like-c-function-to-find-nearest-elements-in-a-container
// Distance
// ========
template <typename T>
struct Distance {
T operator () (const T& a, const T& b) {
return std::abs(a - b);
}
};
// Compare Distance
// ================
template <
typename T,
typename DistanceFunctor = Distance<T>,
typename CompareFunctor = std::less<decltype(
std::declval<DistanceFunctor>()(std::declval<T>(), std::declval<T>()))>>
struct CompareDistance
{
T pivot;
DistanceFunctor distance;
CompareFunctor compare;
CompareDistance(T&& pivot)
: pivot(std::move(pivot))
{}
CompareDistance(T&& pivot, DistanceFunctor&& distance)
: pivot(std::move(pivot)),
distance(std::move(distance))
{}
CompareDistance(T&& pivot, DistanceFunctor&& distance, CompareFunctor&& compare)
: pivot(std::move(pivot)),
distance(std::move(distance)),
compare(std::move(compare))
{}
bool operator () (const T& a, const T& b) {
return compare(distance(a, pivot), distance(b, pivot));
}
};
// Distance Sort
// =============
template <typename Iterator, typename T>
inline void distance_sort(
Iterator first,
Iterator last,
T&& pivot)
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
CompareDistance<value_type> compare_distance(std::move(pivot));
std::sort(first, last, compare_distance);
}
template <typename Iterator, typename T, typename Distance>
inline void distance_sort(
Iterator first,
Iterator last,
T&& pivot,
Distance&& distance)
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
CompareDistance<value_type, Distance> compare_distance(
std::move(pivot),
std::move(distance));
std::sort(first, last, compare_distance);
}
template <typename Iterator, typename T, typename Distance, typename Compare>
inline void distance_sort(
Iterator first,
Iterator last,
T&& pivot,
Distance&& distance,
Compare&& compare)
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
CompareDistance<value_type, Distance, Compare> compare_distance(
std::move(pivot),
std::move(distance),
std::move(compare));
std::sort(first, last, compare_distance);
}