Bug 24803

Summary: [c++0x] reference_wrapper and pointers to member functions
Product: gcc Reporter: John Maddock <john>
Component: libstdc++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED WONTFIX    
Severity: enhancement CC: doug.gregor, fang, gcc-bugs, hhinnant, jwakely.gcc, paolo.carlini
Priority: P3    
Version: 4.0.2   
Target Milestone: ---   
Host: linux.x86 Target: linux.x86
Build: linux.x86 Known to work:
Known to fail: Last reconfirmed: 2006-02-13 04:10:16
Attachments: update result_of and reference_wrapper

Description John Maddock 2005-11-11 16:38:44 UTC
reference_wrapper doesn't seem to be functioning correctly with pointers to member functions.  I'm attaching my test case below.  Note that the actual wording of the  TR is somewhat garbled in this case: but it's covered by TR.DR.10.41.

Regards, John Maddock.

The test case:

#include <tr1/functional>

#include <boost/static_assert.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include "verify_return.hpp"

struct test_type
{
   int member();
   int cmember()const;
   int member2(char);
   int cmember2(char)const;
};

struct functor1 : public std::unary_function<int, double>
{
   double operator()(int)const;
};

struct functor2 : public std::binary_function<int, char, double>
{
   double operator()(int, char)const;
};

int main()
{
   BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::unary_function<int, double>, std::tr1::reference_wrapper<double (int)> >::value));
   BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::unary_function<int, double>, std::tr1::reference_wrapper<double (*)(int)> >::value));
   BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::unary_function<test_type*, int>, std::tr1::reference_wrapper<int (test_type::*)()> >::value));
   BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::unary_function<const test_type*, int>, std::tr1::reference_wrapper<int (test_type::*)()const> >::value));
   BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::unary_function<int, double>, std::tr1::reference_wrapper<functor1> >::value));
   
   BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::binary_function<int, char, double>, std::tr1::reference_wrapper<double (int, char)> >::value));
   BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::binary_function<int, char, double>, std::tr1::reference_wrapper<double (*)(int, char)> >::value));
   BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::binary_function<test_type*, char, int>, std::tr1::reference_wrapper<int (test_type::*)(char)> >::value));
   BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::binary_function<const test_type*, char, int>, std::tr1::reference_wrapper<int (test_type::*)(char)const> >::value));
   BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::binary_function<int, char, double>, std::tr1::reference_wrapper<functor2> >::value));

   // now check operator():
   std::tr1::reference_wrapper<double (int)>* pr1;
   verify_return_type((*pr1)(0), double());
   std::tr1::reference_wrapper<double (*)(int)>* pr2;
   verify_return_type((*pr2)(0), double());
   std::tr1::reference_wrapper<int (test_type::*)()>* pr3;
   verify_return_type((*pr3)(0), int());
   std::tr1::reference_wrapper<int (test_type::*)()const>* pr4;
   verify_return_type((*pr4)(0), int());
   std::tr1::reference_wrapper<functor1>* pr5;
   verify_return_type((*pr5)(0), double());

   std::tr1::reference_wrapper<double (int, char)>* pr1b;
   verify_return_type((*pr1b)(0,0), double());
   std::tr1::reference_wrapper<double (*)(int, char)>* pr2b;
   verify_return_type((*pr2b)(0,0), double());
   std::tr1::reference_wrapper<int (test_type::*)(char)>* pr3b;
   verify_return_type((*pr3b)(0,0), int());
   std::tr1::reference_wrapper<int (test_type::*)()const>* pr4b;
   verify_return_type((*pr4b)(0,0), int());
   std::tr1::reference_wrapper<functor1>* pr5b;
   verify_return_type((*pr5b)(0,0), double());
}

The errors occur on invocation of the function objects:

gcc-C++-action ../../../bin/boost/libs/tr1/test/test_reference_wrapper_tricky.test/gcc-4.0.2/debug/test_reference_wrapper_tricky.o
/home/john/boost/libs/tr1/test/test_reference_wrapper_tricky.cpp: In function `int main()':
/home/john/boost/libs/tr1/test/test_reference_wrapper_tricky.cpp:56: error: no match for call to `(std::tr1::reference_wrapper<int (test_type::*)()>) (int)'
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/ref_wrap_iterate.h:42: note: candidates are: typename std::tr1::result_of<typename std::tr1::_Function_to_function_pointer<_Tp, std::tr1::is_function<_Tp>::value>::type ()()>::type std::tr1::reference_wrapper<_Tp>::operator()() const [with _Tp = int (test_type::*)()]
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/functional_iterate.h:169: note:                 typename std::tr1::result_of<typename std::tr1::reference_wrapper<_Tp>::_M_func_type ()(_T1)>::type std::tr1::reference_wrapper<_Tp>::operator()(_T1&) const [with _T1 = int, _Tp = int (test_type::*)()]
/home/john/boost/libs/tr1/test/test_reference_wrapper_tricky.cpp:58: error: no match for call to `(std::tr1::reference_wrapper<int (test_type::*)()const>) (int)'
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/ref_wrap_iterate.h:42: note: candidates are: typename std::tr1::result_of<typename std::tr1::_Function_to_function_pointer<_Tp, std::tr1::is_function<_Tp>::value>::type ()()>::type std::tr1::reference_wrapper<_Tp>::operator()() const [with _Tp = int (test_type::*)()const]
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/functional_iterate.h:169: note:                 typename std::tr1::result_of<typename std::tr1::reference_wrapper<_Tp>::_M_func_type ()(_T1)>::type std::tr1::reference_wrapper<_Tp>::operator()(_T1&) const [with _T1 = int, _Tp = int (test_type::*)()const]
/home/john/boost/libs/tr1/test/test_reference_wrapper_tricky.cpp:60: error: no match for call to `(std::tr1::reference_wrapper<functor1>) (int)'
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/ref_wrap_iterate.h:42: note: candidates are: typename std::tr1::result_of<typename std::tr1::_Function_to_function_pointer<_Tp, std::tr1::is_function<_Tp>::value>::type ()()>::type std::tr1::reference_wrapper<_Tp>::operator()() const [with _Tp = functor1]
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/functional_iterate.h:169: note:                 typename std::tr1::result_of<typename std::tr1::reference_wrapper<_Tp>::_M_func_type ()(_T1)>::type std::tr1::reference_wrapper<_Tp>::operator()(_T1&) const [with _T1 = int, _Tp = functor1]
/home/john/boost/libs/tr1/test/test_reference_wrapper_tricky.cpp:67: error: no match for call to `(std::tr1::reference_wrapper<int (test_type::*)(char)>) (int, int)'
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/ref_wrap_iterate.h:42: note: candidates are: typename std::tr1::result_of<typename std::tr1::_Function_to_function_pointer<_Tp, std::tr1::is_function<_Tp>::value>::type ()()>::type std::tr1::reference_wrapper<_Tp>::operator()() const [with _Tp = int (test_type::*)(char)]
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/functional_iterate.h:169: note:                 typename std::tr1::result_of<typename std::tr1::reference_wrapper<_Tp>::_M_func_type ()(_T1, _T2)>::type std::tr1::reference_wrapper<_Tp>::operator()(_T1&, _T2&) const [with _T1 = int, _T2 = int, _Tp = int (test_type::*)(char)]
/home/john/boost/libs/tr1/test/test_reference_wrapper_tricky.cpp:69: error: no match for call to `(std::tr1::reference_wrapper<int (test_type::*)()const>) (int, int)'
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/ref_wrap_iterate.h:42: note: candidates are: typename std::tr1::result_of<typename std::tr1::_Function_to_function_pointer<_Tp, std::tr1::is_function<_Tp>::value>::type ()()>::type std::tr1::reference_wrapper<_Tp>::operator()() const [with _Tp = int (test_type::*)()const]
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/functional_iterate.h:169: note:                 typename std::tr1::result_of<typename std::tr1::reference_wrapper<_Tp>::_M_func_type ()(_T1, _T2)>::type std::tr1::reference_wrapper<_Tp>::operator()(_T1&, _T2&) const [with _T1 = int, _T2 = int, _Tp = int (test_type::*)()const]
/home/john/boost/libs/tr1/test/test_reference_wrapper_tricky.cpp:71: error: no match for call to `(std::tr1::reference_wrapper<functor1>) (int, int)'
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/ref_wrap_iterate.h:42: note: candidates are: typename std::tr1::result_of<typename std::tr1::_Function_to_function_pointer<_Tp, std::tr1::is_function<_Tp>::value>::type ()()>::type std::tr1::reference_wrapper<_Tp>::operator()() const [with _Tp = functor1]
/usr/local/gcc/4.0.2/lib/gcc/i686-pc-linux-gnu/4.0.2/../../../../include/c++/4.0.2/tr1/functional_iterate.h:169: note:                 typename std::tr1::result_of<typename std::tr1::reference_wrapper<_Tp>::_M_func_type ()(_T1, _T2)>::type std::tr1::reference_wrapper<_Tp>::operator()(_T1&, _T2&) const [with _T1 = int, _T2 = int, _Tp = functor1]
Comment 1 Paolo Carlini 2005-11-12 12:45:20 UTC
Doug, can you look a bit into this one too? Thanks!
Comment 2 Doug Gregor 2005-11-12 13:23:15 UTC
I don't know how to classify this. The basic problem is one that isn't
really solveable without rvalue references: you can't pass a literal
(e.g., 0) into the operator() of a reference_wrapper or any other
function object in TR1, because the arguments are accepted by
T&. Strictly speaking, this is not a bug. 

However, there are several ways that we could make this work, because
John is doing some very sensible things here [*]. Some ideas are:

  (1) Strong-arm a C++ front-end guru into implementing rvalue references,
      then use them in the TR1 function objects. Heck, we'll need 'em
      for C++0x anyway :)

  (2) When we know the argument types (e.g., when the T in reference_wrapper<T>
      is a function pointer, member function pointer, or class that is derived 
      from unary_function or binary_function), we could inject operator() 
      overloads that have precise type signatures, e.g.,

        T::result_type operator()(T::argument_type const&);

      That's really messy and would require quite a bit of refactoring in 
      reference_wrapper to get right.

  (3) Provide variants of operator() that accept "const T&" arguments in 
      addition to those that accept "T&" arguments. This makes 
      bind/mem_fn/reference_wrapper easier to use, but the number of overloads 
      blows up exponentially. Since we've already run into compilation time 
      issues, we'd have stop doing this once we hit four to five
      arguments (then we get the "I just added one more argument and
      everything blew up!" bug reports).

  (4) Strong-arm a C++ front-end guru into allowing the conversion
      operator (operator T&() const) to actually work for function
      call expressions, making most of reference_wrapper<T>::operator()
      magically go away. (Peter Dimov has suggested this before, but
      it hasn't really worked its way through the committee).


(1) is the forward-looking solution; (2) and (3) are hacks that could
make the code even uglier (ick!). (4) only fixes the problem for
reference_wrapper. At this point, I favor (1) strongly, but I'm not in
a position to strong-arm nor am I in a position to implement rvalue
references myself.

[*] One thing in the code that perhaps shouldn't work is passing the
literal 0 as the argument to 

  reference_wrapper<int (test_type::*)()>::operator()

That means that we need to be able to realize that it's a literal 0
(tricky, messy, but doable; see the construction-from-literal-zero
trick in tr1::function<>) and then convert that to a NULL test_type*.
I don't think John meant to test that, and I don't really think we
should care if it's broken.

A slightly simplified version of John's test case that does work
properly follows. Replace any of null_tt, null_ttc, or zero in the
calls to reference_wrapper objects to trigger compiler errors.

#include <tr1/functional>

struct test_type
{
   int member();
   int cmember()const;
   int member2(char);
   int cmember2(char)const;
};

struct functor1 : public std::unary_function<int, double>
{
   double operator()(int)const;
};

struct functor2 : public std::binary_function<int, char, double>
{
   double operator()(int, char)const;
};

template <class T>
void verify_return_type(T, T)
{
}

int main()
{
   test_type* null_tt = 0;
   const test_type* null_ttc = 0;
   int zero;

   std::tr1::reference_wrapper<double (int)>* pr1;
   verify_return_type((*pr1)(0), double());
   std::tr1::reference_wrapper<double (*)(int)>* pr2;
   verify_return_type((*pr2)(0), double());
   std::tr1::reference_wrapper<int (test_type::*)()>* pr3;
   verify_return_type((*pr3)(null_tt), int());
   std::tr1::reference_wrapper<int (test_type::*)()const>* pr4;
   verify_return_type((*pr4)(null_ttc), int());
   std::tr1::reference_wrapper<functor1>* pr5;
   verify_return_type((*pr5)(zero), double());

   std::tr1::reference_wrapper<double (int, char)>* pr1b;
   verify_return_type((*pr1b)(0,0), double());
   std::tr1::reference_wrapper<double (*)(int, char)>* pr2b;
   verify_return_type((*pr2b)(0,0), double());
   std::tr1::reference_wrapper<int (test_type::*)(char)>* pr3b;
   verify_return_type((*pr3b)(null_tt,zero), int());
   std::tr1::reference_wrapper<int (test_type::*)()const>* pr4b;
   verify_return_type((*pr4b)(null_ttc), int());
   std::tr1::reference_wrapper<functor2>* pr5b;
   verify_return_type((*pr5b)(zero,zero), double());
}
Comment 3 Paolo Carlini 2005-11-12 13:27:22 UTC
Hi Doug. First thing to do, before actually studying your extremely useful and
detailed reply (THANKS), is adding Howard in CC...
Comment 4 John Maddock 2005-11-12 18:32:21 UTC
Doug's right: according to 3.4p4 passing an rvalue results in implementation defined behaviour.  So you can support it or not as you wish.  I'll update the Boost test case accordingly.

However... I predict that that I won't be the first to try and pass an rvalue through a call-wrapper :-)

Regards, John.
Comment 5 Howard Hinnant 2005-11-12 19:02:58 UTC
>   (1) Strong-arm a C++ front-end guru into implementing rvalue references,
>       then use them in the TR1 function objects. Heck, we'll need 'em
>       for C++0x anyway :)

At the risk of being reckless.  Yes...  well, more like YES!!!  ;-)

I know very little about gcc at this point.  But if the feature is implemented under a pragma (say rvalue_refs), default off, and if library code can test the pragma (at the preprocessor level), then we could really move forward (let the puns lie where they may).  N1855 went through core review in Mont Tremblant.  There were several good suggestions on rewording the proposed words, but absolutely nothing against the functionality or even the syntax.  That doesn't mean the syntax is set in concrete.  But it does mean the mud is firming up.  (I am guessing) It will take effort now for N1855 to not be accepted as is, or pretty darn close to it.  The lwg also voiced no complaints and indeed strong support for N1856 - N1862.  Almost irritation that I was taking up committee time with this stuff again (just do it!).

If the language and library work goes under a pragma, default off, we can do the following:

1.  Code like (for reference_wrapper):

#ifdef _GCC_MOVE
    operator()(T1&& t1) const {return (*data_)(std::forward<T1>(t1));}
#else
    operator()(T1& t1) const {return (*data_)(t1);}
#endif

2.  When bug reports like this come in, say "try turning on rvalue reference" (give instructions for doing that).

3.  If the syntax or functionality of the language changes, we are relatively free to change the compiler/lib, documenting as appropriate, since this is not default behavior, and should be documented as an extension - which could change in the future.

4.  When it becomes standard, we set the pragma to default on.

Dealing with bugs like this via hacks is more work than doing it right with rvalue reference.

So who are going to get?  I'd love to do it.  But I'm slightly worse than a newbie in this area.  I could write language tests for it though.  I also wouldn't mind following someone more experienced just for my own education.

How about Russell Yanofsky?

http://russ.hn.org/rref/

It would be best if one did not have to recompile libstdc++ when flipping this pragma.  In order to achieve that you have to be committed to keeping as much out of the binary lib as possible.  To date the direction of libstdc++ has been just the opposite.
Comment 6 Paolo Carlini 2005-11-13 04:34:43 UTC
Ok, therefore suspended (not really invalid, not really open) seems to me an
appropriate status. Otherwise, a mildly "depressing" remark: I'm pretty sure
some people are not very happy with pragmas. I'm pretty sure I read something
to that effect even specifically about rvalue references... But let's discuss
the thing, of course. About thar Russell Yanofsky, no news lately, I read
*months* ago about his willingness to implement rvalue references, then nothing
more happened.
Comment 7 Paolo Carlini 2005-11-13 04:35:09 UTC
Ok, let's suspend it, for now.
Comment 8 Paolo Carlini 2008-01-04 02:32:35 UTC
Hi Doug. Wanted to start updating parts of <functional>, and, as expected, with straightforward rvalue reference changes I can compile the functior1 case. However, I'm not clear about the int (test_type::*)() case, which is indeed failing: can you help me a bit more finding the place where function deals with literal-zero?
Comment 9 Jonathan Wakely 2008-11-05 01:09:38 UTC
Created attachment 16625 [details]
update result_of and reference_wrapper

In the current draft, reference_wrapper invocation requires Callable, which means it should not work for pointers to members. The same is true of result_of, which determines the result of an expression that isn't valid syntax for pointers to members.

That said, here's a patch that updates result_of and reference_wrapper to work for pointers to members as well as callable types, using result_of in place of the Callable concept.  If result_of and reference_wrapper really shouldn't work for pointers to members then this patch would be much simpler, and there's no need for __invoke() either.
Comment 10 Paolo Carlini 2008-11-05 01:25:41 UTC
(In reply to comment #9)
> That said, here's a patch that updates result_of and reference_wrapper to work
> for pointers to members as well as callable types, using result_of in place of
> the Callable concept.  If result_of and reference_wrapper really shouldn't work
> for pointers to members then this patch would be much simpler, and there's no
> need for __invoke() either.

Excellent Jon. Please, commit the patch and let's close the PR for 4.4. A couple of minor nits, if you want: you can remove the main of result_of_neg, being a compile-only testcase; also I think a commented-out VERIFY in result_of can be just removed entirely. Thanks again! (let me know if for some reason you have trouble committing)
Comment 11 Jonathan Wakely 2008-11-05 02:06:58 UTC
Subject: Bug 24803

Author: redi
Date: Wed Nov  5 02:05:59 2008
New Revision: 141596

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=141596
Log:
	PR libstdc++/24803
	PR libstdc++/37351
	* include/tr1_impl/functional (result_of,reference_wrapper): Update
	to use C++0x features.
	* testsuite/20_util/function_objects/return_types/result_of.cc: New.
	* testsuite/20_util/function_objects/return_types/result_of_neg.cc:
	New.
	* testsuite/20_util/function_objects/return_types/result_of_ref.cc:
	New.
	* testsuite/20_util/reference_wrapper/24803.cc: Uncomment FIXMEs.

Added:
    trunk/libstdc++-v3/testsuite/20_util/function_objects/return_types/
    trunk/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of.cc
    trunk/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_neg.cc
    trunk/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_ref.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/tr1_impl/functional
    trunk/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc

Comment 12 Jonathan Wakely 2008-11-05 02:10:20 UTC
Fixed for 4.4 (including the nits you spotted, thanks Paolo)
Comment 13 Jonathan Wakely 2008-11-05 02:27:34 UTC
argh! I've broken call_once, re-opening while I look into it.  A testsuite_files was causing some tests not to run.
Comment 14 Jonathan Wakely 2008-11-05 02:54:50 UTC
the problem is due to bug 35569 - I'll have to revert my patch until I can fix that properly
Comment 15 Paolo Carlini 2008-11-05 08:51:59 UTC
(In reply to comment #14)
> the problem is due to bug 35569 - I'll have to revert my patch until I can fix
> that properly

Argh, too bad. Yes, please revert for now and close libstdc++/38017.
Comment 16 Jonathan Wakely 2009-07-01 12:18:54 UTC
(In reply to comment #9)
> 
> In the current draft, reference_wrapper invocation requires Callable, which
> means it should not work for pointers to members. The same is true of
> result_of, which determines the result of an expression that isn't valid syntax
> for pointers to members.

Could Howard or Doug comment on this?  the Callable concept and result_of both determine the result of an expression  fn(args...)  which in invalid if fn is a pointer to member.

If that's correct, this bug could be closed as INVALID, but that would mean std::bind and std::reference_wrapper do not support features that work with the equivalent components in TR1.  It also means that std::bind<R>() works with pointers to members, even though std::bind() doesn't, because the former doesn't rely on Callable and is only defined in terms of INVOKE which does support pointers to members.


I'm trying to figure out if I need to continue to support this behaviour, or if I can simplify result_of by ignoring pointers to members, but I think this should be an LWG issue.
Comment 17 Paolo Carlini 2009-12-15 17:00:39 UTC
At the moment, not actively working on this...
Comment 18 Jonathan Wakely 2010-01-12 00:54:01 UTC
Subject: Bug 24803

Author: redi
Date: Tue Jan 12 00:53:30 2010
New Revision: 155826

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=155826
Log:
2010-01-12  Jonathan Wakely  <jwakely.gcc@gmail.com>

	PR libstdc++/24803
	PR libstdc++/35569
	PR libstdc++/42593
	* include/std/functional (bind): Forward rvalues and detect correct
	result type of bound function object.
	* include/std/mutex (call_once): Specify bind result type.
	* testsuite/20_util/reference_wrapper/invoke.cc: Remove invalid tests.
	* testsuite/20_util/reference_wrapper/24803.cc: Remove invalid tests
	and enable FIXME tests.
	* testsuite/20_util/bind/35569.cc: New.
	* testsuite/20_util/bind/ref2.cc: New.
	* testsuite/20_util/bind/38889.cc: New.
	* testsuite/20_util/bind/ref_neg.cc: New.
	* testsuite/20_util/bind/42593.cc: New.


Added:
    trunk/libstdc++-v3/testsuite/20_util/bind/35569.cc
    trunk/libstdc++-v3/testsuite/20_util/bind/38889.cc
    trunk/libstdc++-v3/testsuite/20_util/bind/42593.cc
    trunk/libstdc++-v3/testsuite/20_util/bind/ref2.cc
    trunk/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/std/functional
    trunk/libstdc++-v3/include/std/mutex
    trunk/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc
    trunk/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc

Comment 19 Jonathan Wakely 2010-01-12 09:32:30 UTC
As I said earlier in this audit trail, the current draft defines the call operator in terms of std::result_of and so it doesn't support invoking a pointer-to-member. I have removed the relevant bits of the 24803.cc testcase, and enabled the FIXME parts that needed rvalue reference support, which work now that std::reference_wrapper::operator() uses perfect forwarding.
 
I think this bug could be closed now, any objections?
Comment 20 Paolo Carlini 2010-01-12 10:53:26 UTC
(In reply to comment #19)
> I think this bug could be closed now, any objections?

Not from me, I agree it can be closed. I'd like only to make sure we don't forget about the issue with pointers to member functions: is there a DR open already? Maybe we could also find a way to mention it in the code, if you haven't done that already, didn't check.


Comment 21 Jonathan Wakely 2010-01-12 17:19:02 UTC
(In reply to comment #20)
> I'd like only to make sure we don't
> forget about the issue with pointers to member functions: is there a DR open
> already? 

It's been raised on the lib reflector byme, Stephan T. Lavavej and Alisdair Meredith.  I'm not sufficiently motivated to open an issue for it, there are workarounds using mem_fn.

The proposed resolution for LWG 1225 reinforces my interpretation that result_of does not support pointers-to-members.

> Maybe we could also find a way to mention it in the code, if you
> haven't done that already, didn't check.
 
No, I didn't mention it in the code.
Comment 22 Paolo Carlini 2010-01-12 18:07:51 UTC
Interesting... lately people (*) are apparently happy with all sorts of regressions wrt C++98/TR1...

Anyway, then let's close it, actually I leave to you the choice between fixed, wontfix and invalid ;)

(*) Stephan at least is also happy with std::vector & co not explicitly instantiable anymore for non-DefaultConstructible types: if I remember all the time I spent with Matt Austern encouragement to tweak all our containers for that... Agreed, the new philosophy of adding requirements to the specific members allows more flexibility together with non-moveable types, etc, but in my opinion it really makes sense only together with Concepts where you can elegantly make a member "disappear" depending on a Require clause... bah...
Comment 23 Paolo Carlini 2010-01-13 22:21:20 UTC
Ok, for now let's close this as WONTFIX. At your ease, Jon, it would be nice if you could add the # of the reflector message where you raised the issue...
Comment 24 Jonathan Wakely 2010-01-13 23:31:23 UTC
Alisdair asked about it most recently in c++std-lib-24833, Stephan asked before that in c++std-lib-23007

Also related, n1695 proposed making pointers-to-members callable, Doug demonstrated a way to do it with concept maps in c++std-lib-21092