From 8994f2a4dea957c92f09106de1c2fe61a3ae933e Mon Sep 17 00:00:00 2001 From: tusooa Date: Mon, 5 Feb 2024 18:03:51 -0500 Subject: [PATCH] Make zug::compat::invoke work with pointer-to-member function --- test/transducer/map.cpp | 34 ++++++++++++++++++++++++++++++++++ zug/compat/invoke.hpp | 9 +++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/test/transducer/map.cpp b/test/transducer/map.cpp index bec37f5..e7dcb63 100644 --- a/test/transducer/map.cpp +++ b/test/transducer/map.cpp @@ -13,6 +13,7 @@ #include #include +#include using namespace zug; @@ -36,6 +37,11 @@ namespace { int free_times2(int x) { return x * 2; } +struct Foo { + int a; + const int &getA() const { return a; } +}; + } // anonymous namespace TEST_CASE("map, mapping invoke") @@ -43,3 +49,31 @@ TEST_CASE("map, mapping invoke") auto v = std::vector{1, 2, 3, 6}; CHECK(transduce(map(&free_times2), std::plus{}, 1, v) == 25); } + +TEST_CASE("map, pointer to member function") +{ + auto v = std::vector{{1}}; + auto r = into_vector(map(&Foo::getA), v); + CHECK(r == decltype(r){1}); +} + +TEST_CASE("map, pointer to member object") +{ + auto v = std::vector{{1}}; + auto r = into_vector(map(&Foo::a), v); + CHECK(r == decltype(r){1}); +} + +TEST_CASE("map, pointer to member function, invoked via pointer") +{ + auto v = std::vector>{std::shared_ptr(new Foo{1})}; + auto r = into_vector(map(&Foo::getA), v); + CHECK(r == decltype(r){1}); +} + +TEST_CASE("map, pointer to member object, invoked via pointer") +{ + auto v = std::vector>{std::shared_ptr(new Foo{1})}; + auto r = into_vector(map(&Foo::a), v); + CHECK(r == decltype(r){1}); +} diff --git a/zug/compat/invoke.hpp b/zug/compat/invoke.hpp index 01bb235..d49405a 100644 --- a/zug/compat/invoke.hpp +++ b/zug/compat/invoke.hpp @@ -9,6 +9,7 @@ #pragma once #include +#include namespace zug { namespace compat { @@ -22,20 +23,20 @@ template inline auto do_invoke(F&& f, Args&&... args) -> ZUG_DETAIL_DECLTYPE_RETURN( std::forward(f)(std::forward(args)...)) -template +template ::value>> inline auto do_invoke(T Base::*pmd, Derived&& ref) -> ZUG_DETAIL_DECLTYPE_RETURN(std::forward(ref).*pmd) -template +template ::value>> inline auto do_invoke(PMD pmd, Pointer&& ptr) -> ZUG_DETAIL_DECLTYPE_RETURN((*std::forward(ptr)).*pmd) -template +template ::value>> inline auto do_invoke(T Base::*pmf, Derived&& ref, Args&&... args) -> ZUG_DETAIL_DECLTYPE_RETURN((std::forward(ref).* pmf)(std::forward(args)...)) -template +template ::value>> inline auto do_invoke(PMF pmf, Pointer&& ptr, Args&&... args) -> ZUG_DETAIL_DECLTYPE_RETURN(((*std::forward(ptr)).* pmf)(std::forward(args)...))