diff --git a/geometry/src/get.hpp b/geometry/src/get.hpp index 937b77b..2c5e50e 100644 --- a/geometry/src/get.hpp +++ b/geometry/src/get.hpp @@ -6,17 +6,34 @@ #include namespace geometry { +namespace detail { + +template +auto get() -> void = delete; + +template +struct get_fn +{ + template < + class V, + class = std::enable_if_t< + algebra_type_t>::template is_multivector_v< + std::decay_t> and + std::decay_t::template contains>> + constexpr decltype(auto) operator()(V && v) const + { + return get(std::forward(v)); + } +}; + +} // namespace detail + +inline namespace cpo { /// access a blade of a multivector /// -template < - class B, - class V, - class = std::enable_if_t>::template is_multivector_v>>> -constexpr auto get(V&& v) -{ - return get(std::forward(v)); -} +template +inline constexpr auto get = detail::get_fn{}; +} // namespace cpo } // namespace geometry diff --git a/test/BUILD.bazel b/test/BUILD.bazel index 5d0866c..1da6b41 100644 --- a/test/BUILD.bazel +++ b/test/BUILD.bazel @@ -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", diff --git a/test/algebra_get_test.cpp b/test/algebra_get_test.cpp new file mode 100644 index 0000000..93287c2 --- /dev/null +++ b/test/algebra_get_test.cpp @@ -0,0 +1,127 @@ +#include "geometry/geometry.hpp" +#include "skytest/skytest.hpp" + +#include + +template +constexpr auto e = ::geometry::algebra::e; + +template +using blade = typename ::geometry::algebra::template blade; + +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&, decltype(get>(x))>); + static_assert( + std::is_same_v&, decltype(::geometry::get>(x))>); + + static_assert(std::is_same_v&, decltype(get>(x))>); + static_assert( + std::is_same_v&, decltype(::geometry::get>(x))>); + + return expect(true); + }; + + "get const lvalue ref"_ctest = [] { + const auto x = e<> + e<0>; + + using ::geometry::get; + + static_assert(std::is_same_v&, decltype(get>(x))>); + static_assert( + std::is_same_v&, decltype(::geometry::get>(x))>); + + static_assert(std::is_same_v&, decltype(get>(x))>); + static_assert( + std:: + is_same_v&, decltype(::geometry::get>(x))>); + + return expect(true); + }; + + "get rvalue ref"_ctest = [] { + auto x = e<> + e<0>; + + using ::geometry::get; + + static_assert( + std::is_same_v&&, decltype(get>(std::move(x)))>); + static_assert( + std::is_same_v< + blade<>&&, + decltype(::geometry::get>(std::move(x)))>); + + static_assert( + std::is_same_v&&, decltype(get>(std::move(x)))>); + static_assert( + std::is_same_v< + blade<0>&&, + decltype(::geometry::get>(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&&, decltype(get>(std::move(x)))>); + static_assert( + std::is_same_v< + const blade<>&&, + decltype(::geometry::get>(std::move(x)))>); + + static_assert( + std:: + is_same_v&&, decltype(get>(std::move(x)))>); + static_assert( + std::is_same_v< + const blade<0>&&, + decltype(::geometry::get>(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>(x)) {}; + + static_assert(not std::is_invocable_v); + static_assert( + not std:: + is_invocable_v>), 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>(x)) {}; + + static_assert(not std::is_invocable_v); + static_assert( + not std:: + is_invocable_v>), decltype(x)>); + + return expect(true); + }; +}