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 6, 2024
1 parent 4e8617e commit 8994f2a
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
34 changes: 34 additions & 0 deletions test/transducer/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <zug/transducer/take.hpp>

#include <catch2/catch.hpp>
#include <memory>

using namespace zug;

Expand All @@ -36,10 +37,43 @@ 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});
}

TEST_CASE("map, pointer to member function, invoked via pointer")
{
auto v = std::vector<std::shared_ptr<Foo>>{std::shared_ptr<Foo>(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<Foo>>{std::shared_ptr<Foo>(new 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 8994f2a

Please sign in to comment.