http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4383.html#2418
This was voted into the TS in Lenexa. Tested powerpc64le-linux, committed to trunk.
commit ef712e821bc683fe3979251dcc09786bee0233e0 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed May 13 13:37:05 2015 +0100 * include/experimental/tuple (apply): Handle pointers to member (LWG 2418). * include/std/functional (_Mem_fn_base): Make constructors constexpr. (_Maybe_wrap_member_pointer::__do_wrap): Make constexpr. * testsuite/experimental/tuple/apply.cc: Test pointer to member. diff --git a/libstdc++-v3/include/experimental/tuple b/libstdc++-v3/include/experimental/tuple index 4baede4..aa25c57 100644 --- a/libstdc++-v3/include/experimental/tuple +++ b/libstdc++-v3/include/experimental/tuple @@ -36,6 +36,7 @@ #else #include <tuple> +#include <functional> namespace std _GLIBCXX_VISIBILITY(default) { @@ -54,7 +55,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template <typename _Fn, typename _Tuple, std::size_t... _Idx> constexpr decltype(auto) __apply_impl(_Fn&& f, _Tuple&& t, std::index_sequence<_Idx...>) - { return std::forward<_Fn>(f)(get<_Idx>(forward<_Tuple>(t))...); } + { + using _Wrap = _Maybe_wrap_member_pointer<decay_t<_Fn>>; + return _Wrap::__do_wrap(std::forward<_Fn>(f))( + get<_Idx>(forward<_Tuple>(t))...); + } template <typename _Fn, typename _Tuple> constexpr decltype(auto) diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 946cf63..7dd149a 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -572,7 +572,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) public: using result_type = typename _Traits::__result_type; - explicit _Mem_fn_base(_Pmf __pmf) : _M_pmf(__pmf) { } + explicit constexpr _Mem_fn_base(_Pmf __pmf) : _M_pmf(__pmf) { } // Handle objects template<typename... _Args, typename _Req @@ -671,7 +671,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) friend struct _Bind_check_arity; public: - explicit + explicit constexpr _Mem_fn_base(_Res _Class::*__pm) noexcept : _M_pm(__pm) { } // Handle objects @@ -1002,11 +1002,11 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) { typedef _Tp type; - static const _Tp& + static constexpr const _Tp& __do_wrap(const _Tp& __x) { return __x; } - static _Tp&& + static constexpr _Tp&& __do_wrap(_Tp&& __x) { return static_cast<_Tp&&>(__x); } }; @@ -1021,7 +1021,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) { typedef _Mem_fn<_Tp _Class::*> type; - static type + static constexpr type __do_wrap(_Tp _Class::* __pm) { return type(__pm); } }; diff --git a/libstdc++-v3/testsuite/experimental/tuple/apply.cc b/libstdc++-v3/testsuite/experimental/tuple/apply.cc index 88e174d..e52962b 100644 --- a/libstdc++-v3/testsuite/experimental/tuple/apply.cc +++ b/libstdc++-v3/testsuite/experimental/tuple/apply.cc @@ -41,9 +41,23 @@ test02() VERIFY( i == 3 ); } +struct F +{ + int f(int i, int j) const { return i + j; } +}; + +void +test03() +{ + auto t = std::make_tuple(F{}, 1, 2); + int r = std::experimental::apply(&F::f, t); + VERIFY( r == 3 ); +} + int main() { test01(); test02(); + test03(); }