|
Boost : |
From: Joel de Guzman (joel_at_[hidden])
Date: 2007-11-22 03:52:44
shunsuke wrote:
> Joel de Guzman wrote:
>> alas, this uncovers a bug in the implementation where value_at
>> does not follow above.
>
> What is a bug?
See diff of the source in value_at_impl.hpp for the last 2
revisions.
> Is there any pitfall if `value_at` is the same as `at` under transform_view?
After some more thinking, yes.
>> You got me thinking though. It could very well be that you are correct!
>> Perhaps we need the same behavior for both at/deref and value_at/value_of.
>> My thinking, OTOH, is that both should get the value_at of the underlying
>> sequence. Hence, transform(vector<int, int&>, f) will trigger
>> f this way:
>>
>> int ---> f::result<f(int)>
>> int& ---> f::result<f(int&)>
>
> No, when vector<int, int&> is mutable lvalue,
> f should be able to access the mutable int.
> Hence,
>
> int --> f::result<f(int&)>
> int& --> f::result<f(int&)>
I think you are missing the point. It is always mutable with deref and at.
value_at and value_of should allow you to get the *actual* type of
the underlying sequence. Think of value_at and value_of as having
copy semantics.
> The current deref works like this unless as_vector is used.
> It's ok.
That is because as_vector needs to know the actual type of the
underlying sequence, hence it uses value_at/value_of. as_vector
*copies* the source sequence.
> Again,
[snip]
>
> Here, as_vector calls value_of. Hence,
>
> int --> f::result<f(int)>
>
> My poor identity doesn't compile.
> IMHO, as_vector should be able to return vector<int&, int&>.
>
> Once as_vector intervenes, FunctionObject can't access mutable elements in a tuple.
> For example, mutable STL iterator can't be returned from std::string in a tuple.
After some thinking, I am now convinced that the current behavior
is still the proper way to do it. I added an attachment in the
trac ticket that provides the correct way to do the identity
transform. Mutability is not lost; never was. In the case of
as_vector, a copy is generated, not a reference to the original.
This copy has the *exact* same element types of the source
sequence. If value_at were to do as at, then there is no way to
do as_vector correctly if the source vector has a reference element.
Here's a synopsis of what's being returned by at/deref and
value_at/value_of given a vector<int, int&>:
index element type at/deref value_at/value_of
0 T T& T
1 T& T& T&
Notice that value_at/value_of always returns the exact type of
the element. We should not deviate from that behavior. When
a transform is used, it should do the same. Here's what's
happening (given F as the transform function):
index element type at/deref value_at/value_of
0 T F(T&) F(T)
1 T& F(T&) F(T&)
This, I repeat, is the only sensible behavior. If we make
value_at/value_of behave the same as at/deref, then we can
never know the exact type of the elements in the source
container if there are references involved. Given the
"corrected" identity transform I attached in the trac ticket,
the result of the as_vector will be as expected:
vector<int, int&>
(Both vector<int&, int&> and vector<int&, int&> results
are wrong)
For reference, here's the corrected identity transform:
struct identity
{
template <class FunCall>
struct result;
template <class Fun, class T>
struct result<Fun(T)>
{
typedef T type;
};
template <class T>
T& operator()(T& val) const
{
return val;
}
template <class T>
T const& operator()(T const& val) const
{
return val;
}
};
Regards,
-- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk