coord/ops: make 'all' and 'any' constexpr

This commit is contained in:
Danny Robson 2017-08-24 14:32:58 +10:00
parent 14718594c9
commit 84963aacf8
2 changed files with 73 additions and 9 deletions

View File

@ -899,38 +899,90 @@ namespace util {
#undef SCALAR_OP #undef SCALAR_OP
//------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////
namespace detail {
template <
std::size_t S,
template <std::size_t,typename> class K,
std::size_t ...I,
typename = std::enable_if_t<
is_coord_v<K<S,bool>>,
void
>
>
constexpr bool
any (const K<S,bool> k, std::index_sequence<I...>)
{
return (k[I] || ...);
}
};
///---------------------------------------------------------------------------
/// returns true if any element is true.
///
/// this function must be suitable for use in static_assert, so it must remain
/// constexpr.
///
/// we would ideally use std::any_of, but it is not constexpr.
/// we would ideally use range-for, but cbegin is not constexpr.
/// so... moar templates.
template < template <
size_t S, size_t S,
template <size_t,typename> class K, template <size_t,typename> class K,
typename = std::enable_if_t< typename = std::enable_if_t<
is_coord_v<K<S,bool>>, void is_coord_v<K<S,bool>>, void
> >,
typename Indices = std::make_index_sequence<S>
> >
constexpr constexpr
bool bool
any (const K<S,bool> k) any (const K<S,bool> k)
{ {
return std::any_of (std::cbegin (k), return detail::any (k, Indices{});
std::cend (k), }
identity<bool>);
///////////////////////////////////////////////////////////////////////////
namespace detail {
template <
std::size_t S,
template <size_t,typename> class K,
std::size_t ...I,
typename = std::enable_if_t<
is_coord_v<K<S,bool>>,
void
>
>
constexpr bool
all (const K<S,bool> k, std::index_sequence<I...>)
{
return (k[I] && ...);
}
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/// returns true if all elements are true.
///
/// this function must be suitable for use in static_assert, so it must be
/// constexpr.
///
/// we would ideally use std::all_of, but it is not constexpr.
/// we would ideally use range-for, but cbegin is not constexpr.
/// so... moar templates.
template < template <
size_t S, size_t S,
template <size_t,typename> class K, template <size_t,typename> class K,
typename = std::enable_if_t< typename = std::enable_if_t<
is_coord_v<K<S,bool>>, void is_coord_v<K<S,bool>>, void
> >,
typename Indices = std::make_index_sequence<S>
> >
constexpr constexpr
bool bool
all (const K<S,bool> k) all (const K<S,bool> k)
{ {
return std::all_of (std::cbegin (k), return detail::all (k, Indices {});
std::cend (k),
identity<bool>);
} }

View File

@ -54,6 +54,18 @@ main (void)
); );
} }
// test expected outputs for various logical operations
{
constexpr util::point3i a { 0, -1, 2 };
constexpr util::point3i b { 0, 1, -2 };
constexpr util::point3i c { -9, -9, -9 };
tap.expect (!all (a <= b), "all, expected failure");
tap.expect ( all (a <= a), "all, expected success");
tap.expect (!any (a <= c), "any, expected failure");
tap.expect ( any (a <= b), "any, expected success");
};
// ensure the util::select function behaves as expected // ensure the util::select function behaves as expected
{ {
const util::point3f a { -1, 2, 0 }; const util::point3f a { -1, 2, 0 };