Skip to content

Commit

Permalink
fix geometry::get return type (#39)
Browse files Browse the repository at this point in the history
Change-Id: I0dc4d61a67849a28fda34bde45a25784031f6b37
  • Loading branch information
oliverlee authored Jan 29, 2024
1 parent 59d6f45 commit 3d28e0d
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 9 deletions.
35 changes: 26 additions & 9 deletions geometry/src/get.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,34 @@
#include <utility>

namespace geometry {
namespace detail {

template <class T>
auto get() -> void = delete;

template <class B>
struct get_fn
{
template <
class V,
class = std::enable_if_t<
algebra_type_t<std::decay_t<V>>::template is_multivector_v<
std::decay_t<V>> and
std::decay_t<V>::template contains<B>>>
constexpr decltype(auto) operator()(V && v) const
{
return get<B>(std::forward<V>(v));
}
};

} // namespace detail

inline namespace cpo {

/// access a blade of a multivector
///
template <
class B,
class V,
class = std::enable_if_t<algebra_type_t<
std::decay_t<V>>::template is_multivector_v<std::decay_t<V>>>>
constexpr auto get(V&& v)
{
return get<B>(std::forward<V>(v));
}
template <class B>
inline constexpr auto get = detail::get_fn<B>{};

} // namespace cpo
} // namespace geometry
10 changes: 10 additions & 0 deletions test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ cc_test(
],
)

cc_test(
name = "algebra_get_test",
size = "small",
srcs = ["algebra_get_test.cpp"],
deps = [
"//:geometry",
"@skytest",
],
)

cc_test(
name = "algebra_pruned_expressions_test",
size = "small",
Expand Down
127 changes: 127 additions & 0 deletions test/algebra_get_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include "geometry/geometry.hpp"
#include "skytest/skytest.hpp"

#include <utility>

template <std::size_t... Is>
constexpr auto e = ::geometry::algebra<double, 2>::e<Is...>;

template <std::size_t... Is>
using blade = typename ::geometry::algebra<double, 2>::template blade<Is...>;

auto main() -> int
{
using namespace ::skytest::literals;
using ::skytest::eq;
using ::skytest::expect;

"get lvalue ref"_ctest = [] {
auto x = e<> + e<0>;

using ::geometry::get;

static_assert(std::is_same_v<blade<>&, decltype(get<blade<>>(x))>);
static_assert(
std::is_same_v<blade<>&, decltype(::geometry::get<blade<>>(x))>);

static_assert(std::is_same_v<blade<0>&, decltype(get<blade<0>>(x))>);
static_assert(
std::is_same_v<blade<0>&, decltype(::geometry::get<blade<0>>(x))>);

return expect(true);
};

"get const lvalue ref"_ctest = [] {
const auto x = e<> + e<0>;

using ::geometry::get;

static_assert(std::is_same_v<const blade<>&, decltype(get<blade<>>(x))>);
static_assert(
std::is_same_v<const blade<>&, decltype(::geometry::get<blade<>>(x))>);

static_assert(std::is_same_v<const blade<0>&, decltype(get<blade<0>>(x))>);
static_assert(
std::
is_same_v<const blade<0>&, decltype(::geometry::get<blade<0>>(x))>);

return expect(true);
};

"get rvalue ref"_ctest = [] {
auto x = e<> + e<0>;

using ::geometry::get;

static_assert(
std::is_same_v<blade<>&&, decltype(get<blade<>>(std::move(x)))>);
static_assert(
std::is_same_v<
blade<>&&,
decltype(::geometry::get<blade<>>(std::move(x)))>);

static_assert(
std::is_same_v<blade<0>&&, decltype(get<blade<0>>(std::move(x)))>);
static_assert(
std::is_same_v<
blade<0>&&,
decltype(::geometry::get<blade<0>>(std::move(x)))>);

return expect(true);
};

"get const rvalue ref"_ctest = [] {
const auto x = e<> + e<0>;

using ::geometry::get;

// NOLINTBEGIN(performance-move-const-arg)

static_assert(
std::is_same_v<const blade<>&&, decltype(get<blade<>>(std::move(x)))>);
static_assert(
std::is_same_v<
const blade<>&&,
decltype(::geometry::get<blade<>>(std::move(x)))>);

static_assert(
std::
is_same_v<const blade<0>&&, decltype(get<blade<0>>(std::move(x)))>);
static_assert(
std::is_same_v<
const blade<0>&&,
decltype(::geometry::get<blade<0>>(std::move(x)))>);

// NOLINTEND(performance-move-const-arg)

return expect(true);
};

"get not used with multivector"_ctest = [] {
const auto b = e<1>;

using geometry::get;
auto f = [](auto x) -> decltype(get<blade<1>>(x)) {};

static_assert(not std::is_invocable_v<decltype(f), decltype(b)>);
static_assert(
not std::
is_invocable_v<decltype(::geometry::get<blade<1>>), decltype(b)>);

return expect(true);
};

"blade not in multivector"_ctest = [] {
const auto x = e<> + e<0>;

using ::geometry::get;
auto f = [](auto x) -> decltype(get<blade<1>>(x)) {};

static_assert(not std::is_invocable_v<decltype(f), decltype(x)>);
static_assert(
not std::
is_invocable_v<decltype(::geometry::get<blade<1>>), decltype(x)>);

return expect(true);
};
}

0 comments on commit 3d28e0d

Please sign in to comment.