-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implement min_element (guarded for SFINAE)
- Loading branch information
ecrypa
committed
Oct 9, 2019
1 parent
ebda810
commit 7e1f955
Showing
3 changed files
with
235 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#ifndef METAL_LIST_MIN_ELEMENT_HPP | ||
#define METAL_LIST_MIN_ELEMENT_HPP | ||
|
||
#include "../config.hpp" | ||
#include "../lambda/apply.hpp" | ||
#include "../lambda/lambda.hpp" | ||
#include "../lambda/partial.hpp" | ||
#include "../number/if.hpp" | ||
#include "../value/fold_left.hpp" | ||
|
||
namespace metal { | ||
namespace detail { | ||
template<bool> | ||
struct _min_element_binary_expr_guard { | ||
template<template<class...> class expr, class a, class b> | ||
using type = expr<a, b>; | ||
}; | ||
|
||
template<class...> | ||
struct _guard { // alternate version for arity n, but possibly(?) slower | ||
template<template<class...> class expr, class... args> | ||
using type = expr<args...>; | ||
}; | ||
|
||
template<typename lbd> | ||
struct _min_element {}; | ||
|
||
template<template<class...> class expr> | ||
struct _min_element<lambda<expr>> { | ||
template<class x, class y, class... empty> | ||
using combiner = | ||
if_<typename _min_element_binary_expr_guard<!sizeof...( | ||
empty)>::template type<expr, y, x>, | ||
y, x>; | ||
|
||
template<class x, class y, class... _> | ||
using more_general_but_possibly_slower_combiner = // TODO: benchmark | ||
if_<typename _guard<_...>::template type<expr, y, x>, y, x>; | ||
|
||
template<class seq> | ||
using type = | ||
apply<partial<lambda<fold_left>, lambda<combiner>>, seq>; | ||
}; | ||
|
||
} // detail | ||
|
||
template<typename seq, typename lbd> | ||
using min_element = typename detail::_min_element<lbd>::template type<seq>; | ||
} // metal | ||
|
||
#endif |