------- Comment #2 from doug dot gregor at gmail dot com 2005-11-12 13:23 ------- 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()); } -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24803