
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