coord/base: add indices query using supplemental values

This commit is contained in:
Danny Robson 2019-03-22 11:54:29 +11:00
parent 4cf6bb292b
commit 0d9374d3dd
2 changed files with 56 additions and 8 deletions

View File

@ -232,22 +232,63 @@ namespace cruft::coord {
///////////////////////////////////////////////////////////////////////
/// returns an instance with elements specified by the Indices
/// Returns an instance with elements specified by the Indices
/// parameter. eg, point2f p{}.indices<0,2> would return {p.x, p.z}.
///
/// it's ugly as sin, but simplifies some situations where we don't
/// want a temporary.
template <std::size_t ...Indices>
/// Given we don't take any arguments all indices must be valid for
/// the current object.
template <
std::size_t ...Indices,
typename = std::enable_if_t<cruft::max (Indices...) < S>
>
constexpr auto
indices (void) const
{
return redim_t<SelfT,sizeof...(Indices)> {
this->data[Indices]...
};
}
/// Return an instance of the same type where the elements of the new
/// value area specified by the Indices... template parameter.
///
/// If the index is greater than the maximum index of this type then
/// the value is taken from a pack of supplementary values.
///
/// eg, vector2f{0,1}.indices<0,2,1> (2) would result in {0,2,1}
template <
std::size_t ...Indices,
typename ...U,
typename = std::enable_if_t<
// At least one index doesn't address our current data
cruft::max (Indices...) >= S &&
// The new data type must be the old data type
(std::is_same_v<T,U> && ...)
>
>
constexpr auto
indices (U&& ...supplementary) const
{
static_assert (
all (make_vector ((Indices < S)...)),
cruft::max (Indices...) < S + sizeof...(supplementary),
"indices must fall within the defined range for the type"
);
// Expand the pack using either:
// * data from ourselves,
// * or rebasing the index into a tuple of the supplementary values
//
// The index to std::get _must_ be valid even if we don't use the
// result (otherwise we tend to encounter static assertions). Thus
// we conditionally specify a zero index if we know it won't get
// used.
return redim_t<SelfT,sizeof...(Indices)> {
this->data[Indices]...
Indices < S
? this->data[Indices]
: std::get<
(Indices > S) ? Indices - S : 0
> (std::tuple (supplementary...))...
};
}
};

View File

@ -104,9 +104,16 @@ main (void)
// ensure that klass::indices appears to link correctly
{
const cruft::vector3i seq { 0, 1, 2 };
const cruft::vector4i res { 2, 0, 0, 1 };
tap.expect_eq (seq.indices<2,0,0,1> (), res, "coord::indices expansion");
{
const cruft::vector4i res { 2, 0, 0, 1 };
tap.expect_eq (seq.indices<2,0,0,1> (), res, "coord::indices expansion");
}
{
const cruft::vector4i res { 2, 3, 4, 0 };
tap.expect_eq (seq.indices<2,3,4,0> (3, 4), res, "coord::indices supplemental expansion");
}
};
// ensure that cruft::shift operations appear to operate correctly