
On 3/22/07, shunsuke <pstade.mb@gmail.com> wrote:
Daniel Walker wrote:
On 3/21/07, shunsuke <pstade.mb@gmail.com> wrote:
Daniel Walker wrote:
If/when lambda standardizes on result<>, the lambda related special cases in result_of can be removed. It will break a code using not result_of but sig compatible functors?
Yes. That's the reason lambda would support both for a time with sig<> being deprecated. After a release or two (giving users plenty of time to update their code) sig<> would be removed. This gives them a fair warning and time to adapt.
I think users don't want to spend the time. Smart users will protect themselves right now by using something like..
struct sig_compatible_fun : enable_result_of_sig // added { // ... };
Hmm, patch is no longer required. :-)
There are lots of ways that users can work around the fact that result_of can't work with lambda. We've discussed several. There are usually ways for users to work around missing features and/or bugs in the 3rd party libraries they use. The point of my patches are to make result_of work with lambda without requiring additional user effort. I believe this is a reasonable expectation. I first ran into this problem because the Boost.Parameter library explicitly told users to use lambda and then passed the lambda functor to result_of. When it didn't work, it appeared like a bug in the parameter library. So, I think it is not an uncommon disappointment among boost users and developers that lambda and result_of don't play nicely together out of the box. Plus, as Eric pointed out earlier in this thread, the result_of convention of using result<> for return types is now standard (is that TR1?). Why shouldn't lambda follow it? An alternative might be to leave result_of unchanged but provide a converter along the lines of your suggestion: a function adapter that would make lambda expressions usable in result_of. Boost users could use this with lambda expressions and their own lambda compatible functors. Boost.Parameter could use it to make lazy binding work as advertised. However, in the long run it seems like there should be a single convention for specifying argument dependent return types using result<>, and user expectations such as boost libraries being interoperable should be met as much as possible.
Can the patch support a sig compatible functor which is "nullary-callable" (e.g. lambda::constructor<>) ?
Yes. I just tested it with lambda::constructor<>, and it does work.
I tried this:
#include <boost/utility/result_of.hpp> #include <boost/lambda/construct.hpp>
int main() { using boost::lambda::constructor; using boost::result_of;
int i = 1; result_of<constructor<int>(int&)>::type r = constructor<int>()(i); // (1) GCC compiles.
result_of<constructor<int>()>::type r = constructor<int>()(); // (2) GCC fails. }
I missed this. I tested with something like ... template<class F> void f(F const& f) { typename result_of< F() >::type y = f(); } int main() { using namespace lambda; f(bind(constructor<int>())); } ... which works due to the resul_ot patch, not the lambda patch. I'll explain. As I understand it, the problem here is two fold. First, the result_of documentation states that: "result_of<F(T1, T2, ..., TN)> is F::result<F(T1, T2, ..., TN)>::type when N > 0 or void when N = 0." So, any nullary result_of<F()> will be void unless F provides result_type. The same is true if F provides sig<>... with one exception: if F is generated from a lambda expression result_of<F()> will deduce the correct type. constructor<> isn't a lambda expression. It's a wrapper class that can be used as a target function of lambda::bind expressions. Second, I inadvertently made the type deduction in result_of more powerful for lambda expression than the usual functors. It can correctly deduce the return types of a lambda::lambda_functor taking zero or more arguments. result_of can not deduce the return types of any arbitrary functor F which overrides operator() for zero or more arguments due to the fact that when the number of arguments for F::result<F()> is zero result_of always evals to void. You can't supply a F::result_type for this case because it will be preferred over the F::result<> for the operator()s that take arguments. It seems to me that this limitation is simple to overcome if you make result_of dependent on whether the functor provides a result_type or result<> (or sig<>) instead of the number of arguments. The documentation would read something like the following. "When F is a class type with a member type result_type, result_of<F(T1, T2, ..., TN)> is F::result_type. Otherwise, if F is a class type with a member type F::result<F(T1, T2, ..., TN)>::type, result_of<F(T1, T2, ..., TN)>::type is F::result<F(T1, T2, ..., TN)>::type. Otherwise, result_of<F(T1, T2, ..., TN)>::type is void for N >= 0." The third case could be changed to be dependent on the number of arguments (after giving the user a chance to supply result_type or result<>) if that's preferable. This is simple to implement with has_template_xxx. Am I missing something? If it's impossible to make the above changes due to the fact that the behavior has already been standardized, I could instead provide specializations for result_of with nullary lambda expressions (and helper classes like construct) in the lambda library and get the same effect. This is what Douglas suggested for users to do in the rationale sited below.
I guess a sig-compatible functor which is nullary-callable must be ported to result_of, even if the patch is applied.
The same is true for a result-compatible functor as described above. This is an existing limitation of result_of which we may or may not want to address.
Note that nullary instantiation of 'result_of' must always succeed. (See the rationale at http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html)
I believe the errors you're seeing are due to the assignment to r (which is declared void) and not to result_of<constructor<int>()> being ill-formed.
Well, I have bad news. VC++7.1 and VC8 can't compile (1) nor (2). :-(
Could you send the error messages you're getting for (1)? (2) won't compile due to the limitation that result_of always ignores nullary F::result<F()>::type.
I introduce <boost/detail/functionN.hpp> at Boost.Accumulators, which seems very cool.
I looked for your file in the boost-sandbox cvs repository and couldn't find it. Could you send a link?
See the accumulators.zip in "Math - Numerics" directory at Boost Vault.
I'll check it out. Thanks again! Daniel