$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [result_of, tr1] decltype and incomplete types
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-04-12 19:02:25
On Mon, Apr 12, 2010 at 1:28 PM, Eric Niebler <eric_at_[hidden]> wrote:
> On 4/12/2010 8:05 AM, Daniel Walker wrote:
>> On Sun, Apr 11, 2010 at 5:47 PM, Eric Niebler <eric_at_[hidden]> wrote:
>>> The regression test failures may be more evidence that the change to
>>> result_of was a bad idea (as well-intentioned as it may have seemed).
>>> This patch may not be the last word on the issue. I'm still
>>> uncomfortable with the change to boost::result_of, which is likely to
>>> break users' code. Perhaps we could place the new decltype
>>> implementation on a compile-time switch (BOOST_RESULT_OF_USE_DECLTYPE?)
>>> so that users can opt in. That wouldn't eliminate the need for
>>> boost::tr1_result_of or something like it, though.
>>
>> Ultimately, boost::result_of should behave as intended whenever
>> possible; i.e. it should evaluate to the type of a call expression.
> <snip>
>
> This is a strident position ... and wrong. Intention has nothing to do
> with it. Boost::result_of should behave as *specified*. The current
> documentation for boost::result_of specify it to use the TR1 result_of
> protocol. Users have come to rely on it. The TR1 behavior is not a bug.
> It's a standard.
I don't mean to be stridently wrong. :) Let me try to explain. The
boost::result_of documentation says the following:
"The class template result_of helps determine the type of a call
expression. Given an lvalue f of type F and lvalues t1, t2, ..., tN of
types T1, T2, ..., TN, respectively, the type result_of<F(T1, T2, ...,
TN)>::type defines the result type of the expression f(t1, t2,
...,tN)."
In the strictest sense, this is only true in TR1 if F is a function
pointer, function reference or member function pointer. If F is a
class type, result_of<F(T1, T2, ..., TN)>::type could be any type and
may have nothing to do with the expression f(t1, t2, ...,tN),
depending on whether F::result<> meets the "intention" of the
specification. result_of is specified to give the type of
f(t1, t2, ...,tN). If, for whatever reason, it is not the type of
f(t1, t2, ...,tN), then that is a "bug," in some sense. In c++0x,
result_of can treat class types the same way as function pointers,
function references and member function pointers; i.e. it can give the
type of f(t1, t2, ...,tN) for any F, so this sort of bug is no longer
possible.
>
> And if you want to talk about *standard* specifications, there are 2 to
> choose from (or will be soon): TR1 and C++0x. One can be implemented
> with complete fidelity on every major supported compiler. The other can
> only be supported on the newest compilers and is still in flux due to a
> bug in the specification of decltype. I think going with the second is
> premature, even if you forget about the LOCs you'll break.
>
> Intentions and specifications aside, you are now the maintainer of one
> of the most heavily used and essential pieces of Boost infrastructure.
> Not breaking code should be a factor in your decisions. If you want to
> change behavior, you need a migration path. Putting the new
> (experimental and buggy) behavior on a switch so users can opt in is a
> reasonable first step. It should be accompanied with documentation,
> release notes, and an effort to educate boost developers and users about
> ways to find their portability/migration issues so that their code works
> with a decltype-based result_of. We may decide to hold here for a few
> releases, or until vendors start shipping non-broken decltype
> implementations. Only after folks have had sufficient warning and time
> to adapt could we think about making decltype the default.
I agree with the priorities you've expressed, and I'm glad you've
pressed the issue here and on CWG. I think we're coming to a better
understanding of things, now, and we can continue ironing out these
issues after 1.43.
Daniel Walker