Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

use metal::less as default ordering for metal::sort #101

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions example/src/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,11 @@ IS_SAME(
metal::sort<l, metal::lambda<not_bigger>>, // non-stable sorting
metal::list<uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t>
);

IS_SAME(
metal::sort<metal::numbers<7, -8, -3, 2>>, // use default ordering
metal::sort<metal::numbers<7, -8, -3, 2>, metal::lambda<metal::less>>
);
/// [sort]
)

Expand Down
19 changes: 15 additions & 4 deletions include/metal/list/sort.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@

#include "../config.hpp"
#include "../detail/sfinae.hpp"
#include "../lambda/lambda.hpp"
#include "../list/list.hpp"
#include "../number/if.hpp"
#include "../number/less.hpp"

namespace metal {
/// \cond
namespace detail {
template<class lbd>
template<class lbd = metal::lambda<metal::less>>
brunocodutra marked this conversation as resolved.
Show resolved Hide resolved
struct _sort;
}
/// \endcond
Expand All @@ -19,7 +21,7 @@ namespace metal {
/// ### Description
/// Sorts the elements of a \list according to an ordering relation.
///
/// \tip{The sorting is [stable] if the ordering relation is [strict].}
/// \note{The sorting is [stable] if the ordering relation is [strict].}
/// [stable]: https://en.wikipedia.org/wiki/Sorting_algorithm#Stability
/// [strict]: https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings
///
Expand All @@ -41,18 +43,27 @@ namespace metal {
/// such that `metal::invoke<lbd, val_i, val_i+1>{} != false` for all
/// `i` in `[0, m-2]`.
///
/// \tip{`lbd` may be omitted, in which case it defaults to `metal::lambda<metal::less>`.}
///
/// ### Example
/// \snippet list.cpp sort
///
/// ### See Also
/// \see list, reverse, rotate
template<class seq, class lbd>
#if !defined(METAL_WORKAROUND)
template<class seq, class lbd = metal::lambda<metal::less>>
using sort = detail::call<
detail::_sort<lbd>::template type,
metal::if_<metal::is_list<seq>, seq>>;
#else
// MSVC 14 has shabby SFINAE support in case of default alias template args
template<class seq, class... lbd>
using sort = detail::call<
detail::_sort<lbd...>::template type,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind if I open a couple of PRs in order to test different versions? Or should I prefer godbolt.org in order to reduce the load of your CI setup?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind extra PRs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried, but I think it is not worth any more effort. I vote for the workaround.

metal::if_<metal::is_list<seq>, seq>>;
#endif
}

#include "../lambda/lambda.hpp"
#include "../list/prepend.hpp"
#include "../list/range.hpp"
#include "../list/size.hpp"
Expand Down
18 changes: 18 additions & 0 deletions test/unit/src/metal/list/sort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,63 @@
#include "test.hpp"

#define MATRIX(M, N) \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, VALUE(M)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, VALUE(M), VALUE(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, VALUE(M), NUMBER(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, VALUE(M), PAIR(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, VALUE(M), LIST(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, VALUE(M), MAP(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, VALUE(M), LAMBDA(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, NUMBER(M)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, NUMBER(M), VALUE(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, NUMBER(M), NUMBER(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, NUMBER(M), PAIR(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, NUMBER(M), LIST(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, NUMBER(M), MAP(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, NUMBER(M), LAMBDA(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, NUMBER(M), LAMBDA(_)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, PAIR(M)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, PAIR(M), VALUE(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, PAIR(M), NUMBER(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, PAIR(M), PAIR(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, PAIR(M), LIST(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, PAIR(M), MAP(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, PAIR(M), LAMBDA(N)>), (BOOL(N == 2))); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, PAIR(M), LAMBDA(_)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LIST(M)>), (BOOL(M < 2))); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LIST(M), VALUE(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LIST(M), NUMBER(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LIST(M), PAIR(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LIST(M), LIST(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LIST(M), MAP(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LIST(M), LAMBDA(N)>), (BOOL(N == 2 || M < 2))); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LIST(M), LAMBDA(_)>), (BOOL(M < 2))); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, MAP(M)>), (BOOL(M < 2))); \
ecrypa marked this conversation as resolved.
Show resolved Hide resolved
CHECK((metal::is_invocable<metal::lambda<metal::sort>, MAP(M), VALUE(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, MAP(M), NUMBER(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, MAP(M), PAIR(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, MAP(M), LIST(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, MAP(M), MAP(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, MAP(M), LAMBDA(N)>), (BOOL(N == 2 || M < 2))); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, MAP(M), LAMBDA(_)>), (BOOL(M < 2))); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, metal::list<NUMBERS(M)>>), (TRUE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, metal::list<NUMBERS(M)>, VALUE(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, metal::list<NUMBERS(M)>, NUMBER(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, metal::list<NUMBERS(M)>, PAIR(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, metal::list<NUMBERS(M)>, LIST(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, metal::list<NUMBERS(M)>, MAP(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, metal::list<NUMBERS(M)>, metal::list<NUMBERS(N)>>), (FALSE)); \
brunocodutra marked this conversation as resolved.
Show resolved Hide resolved
CHECK((metal::is_invocable<metal::lambda<metal::sort>, metal::list<NUMBERS(M)>, LAMBDA(N)>), (BOOL(N == 2 || M < 2))); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, metal::list<NUMBERS(M)>, LAMBDA(_)>), (BOOL(M < 2))); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(M)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(M), VALUE(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(M), NUMBER(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(M), PAIR(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(M), LIST(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(M), MAP(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(M), LAMBDA(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(M), LAMBDA(_)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(_)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(_), VALUE(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(_), NUMBER(N)>), (FALSE)); \
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(_), PAIR(N)>), (FALSE)); \
Expand All @@ -53,7 +69,9 @@
CHECK((metal::is_invocable<metal::lambda<metal::sort>, LAMBDA(_), LAMBDA(_)>), (FALSE)); \
CHECK((metal::sort<metal::list<NUMBERSX20(M)>, metal::lambda<metal::greater>>), (metal::list<RENUM(M, FWD, NUMBERX20)>)); \
CHECK((metal::sort<metal::list<NUMBERSX20(M)>, metal::lambda<metal::less>>), (metal::list<NUMBERSX20(M)>)); \
CHECK((metal::sort<metal::list<NUMBERSX20(M)>>), (metal::list<NUMBERSX20(M)>)); \
CHECK((metal::sort<metal::list<ENUM(INC(N), NUMBERS FIX(INC(M)))>, metal::lambda<metal::less>>), (metal::list<ENUM(INC(M), FWD, RENUM(INC(N), NUMBER NIL))>)); \
CHECK((metal::sort<metal::list<ENUM(INC(N), NUMBERS FIX(INC(M)))>>), (metal::list<ENUM(INC(M), FWD, RENUM(INC(N), NUMBER NIL))>)); \
/**/

GEN(MATRIX)