Skip to content

Commit

Permalink
Make zug::compat::invoke work with pointer-to-member function
Browse files Browse the repository at this point in the history
  • Loading branch information
tusooa committed Feb 5, 2024
1 parent 4e8617e commit 065d97b
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 4 deletions.
19 changes: 19 additions & 0 deletions test/transducer/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,29 @@ 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")
{
auto v = std::vector<int>{1, 2, 3, 6};
CHECK(transduce(map(&free_times2), std::plus<int>{}, 1, v) == 25);
}

TEST_CASE("map, pointer to member function")
{
auto v = std::vector<Foo>{{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<Foo>{{1}};
auto r = into_vector(map(&Foo::a), v);
CHECK(r == decltype(r){1});
}
9 changes: 5 additions & 4 deletions zug/compat/invoke.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#pragma once

#include <utility>
#include <type_traits>

namespace zug {
namespace compat {
Expand All @@ -22,20 +23,20 @@ template <class F, class... Args>
inline auto do_invoke(F&& f, Args&&... args) -> ZUG_DETAIL_DECLTYPE_RETURN(
std::forward<F>(f)(std::forward<Args>(args)...))

template <class Base, class T, class Derived>
template <class Base, class T, class Derived, class = std::enable_if_t<!std::is_function<T>::value>>
inline auto do_invoke(T Base::*pmd, Derived&& ref)
-> ZUG_DETAIL_DECLTYPE_RETURN(std::forward<Derived>(ref).*pmd)

template <class PMD, class Pointer>
template <class PMD, class Pointer, class = std::enable_if_t<std::is_member_object_pointer<PMD>::value>>
inline auto do_invoke(PMD pmd, Pointer&& ptr)
-> ZUG_DETAIL_DECLTYPE_RETURN((*std::forward<Pointer>(ptr)).*pmd)

template <class Base, class T, class Derived, class... Args>
template <class Base, class T, class Derived, class... Args, class = std::enable_if_t<std::is_function<T>::value>>
inline auto do_invoke(T Base::*pmf, Derived&& ref, Args&&... args)
-> ZUG_DETAIL_DECLTYPE_RETURN((std::forward<Derived>(ref).*
pmf)(std::forward<Args>(args)...))

template <class PMF, class Pointer, class... Args>
template <class PMF, class Pointer, class... Args, class = std::enable_if_t<std::is_member_function_pointer<PMF>::value>>
inline auto do_invoke(PMF pmf, Pointer&& ptr, Args&&... args)
-> ZUG_DETAIL_DECLTYPE_RETURN(((*std::forward<Pointer>(ptr)).*
pmf)(std::forward<Args>(args)...))
Expand Down

0 comments on commit 065d97b

Please sign in to comment.