[proto v4 docs]Suggest warning about transform composition failure

The attached fails to compile because when the output of one when transform is immediately fed to another transform, the compiler complains because it expects Expr& instead of Expr as 1st arg to the composition. Although the docs on: libs/proto/doc/html/boost_proto/appendices/rationale/result_of.html *hint* that this could happen, it's not obvious. It would have helped me to see this on that page. IOW, that page could specifically say that transform compositions are not possible because a transform expects Expr& and when transforms are composed without storing intermediate values in a variable, then the 1st transform produces an Expr and not an Expr&; so, the second transform rejects it.

On 05/17/08 10:52, Larry Evans wrote: [snip]
me to see this on that page. IOW, that page could specifically say that transform compositions are not possible because a transform expects Expr& and when transforms are composed without storing intermediate values in a variable, then the 1st transform produces an Expr and not an Expr&; so, the second transform rejects it. Except when the composed transforms are pass_through transforms. In this case, it works, as shown by compiling the attached, which is a slight modification of previous attachment. That seems inconsistent or, at least, unexpected behavior for transforms.
What's the rationale for this behavior?

Larry Evans wrote:
The attached fails to compile because when the output of one when transform is immediately fed to another transform, the compiler complains because it expects Expr& instead of Expr as 1st arg to the composition.
Hi Larry, The file you attached compiles fine for me against the proto/v4 branch. What version of proto are you using? -- Eric Niebler Boost Consulting www.boost-consulting.com

On 05/19/08 18:24, Eric Niebler wrote:
Larry Evans wrote:
The attached fails to compile because when the output of one when transform is immediately fed to another transform, the compiler complains because it expects Expr& instead of Expr as 1st arg to the composition.
Hi Larry,
The file you attached compiles fine for me against the proto/v4 branch. What version of proto are you using?
This is a record of svn update: <--- cut here --- -*- mode: compilation; default-directory: "~/prog_dev/boost-svn/ro/branches-proto-v4/" -*- Compilation started at Fri May 16 07:24:21 svn update U configure U status/explicit-failures-markup.xml U status/Jamfile.v2 D boost/intrusive/pointer_plus_bit.hpp ... U tools/jam/src/compile.c U tools/jam/src/builtins.c U tools/jam/src U Jamroot U . Updated to revision 45423. Compilation finished at Fri May 16 07:24:36
--- cut here ---

Larry Evans wrote:
On 05/19/08 18:24, Eric Niebler wrote:
The file you attached compiles fine for me against the proto/v4 branch. What version of proto are you using?
This is a record of svn update: <--- cut here --- -*- mode: compilation; default-directory: "~/prog_dev/boost-svn/ro/branches-proto-v4/" -*- Compilation started at Fri May 16 07:24:21
svn update U configure U status/explicit-failures-markup.xml U status/Jamfile.v2 D boost/intrusive/pointer_plus_bit.hpp ... U tools/jam/src/compile.c U tools/jam/src/builtins.c U tools/jam/src U Jamroot U . Updated to revision 45423.
Compilation finished at Fri May 16 07:24:36
Um, does this mean you're using the proto/v4 branch? Are you still having problems, or have they gone away? Can you send a compiler error and steps to repro? 'Cause it works over here. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 05/19/08 18:51, Eric Niebler wrote:
Larry Evans wrote:
On 05/19/08 18:24, Eric Niebler wrote:
The file you attached compiles fine for me against the proto/v4 branch. What version of proto are you using?
This is a record of svn update: <--- cut here --- -*- mode: compilation; default-directory: "~/prog_dev/boost-svn/ro/branches-proto-v4/" -*- Compilation started at Fri May 16 07:24:21
svn update U configure U status/explicit-failures-markup.xml U status/Jamfile.v2 D boost/intrusive/pointer_plus_bit.hpp ... U tools/jam/src/compile.c U tools/jam/src/builtins.c U tools/jam/src U Jamroot U . Updated to revision 45423.
Compilation finished at Fri May 16 07:24:36
Um, does this mean you're using the proto/v4 branch?
Yes.
Are you still having problems, or have they gone away?
They're still there.
Can you send a compiler error and steps to repro? 'Cause it works over here.
The attachment on 1st post has '#if 1' around line 117. That should produce the error. The 2nd post's attachment has '#if 0' and doesn't produce an error. When you run, do you use '#if 1' or not? The complete bjam output of 2nd post's attachment with '#if 1' is attached as bjam.out. The Jamfile in <boost-root>/sandbox/ is attached as Jamfile. -*- mode: compilation; default-directory: "~/prog_dev/boost-svn/ro/branches-proto-v4/sandbox/lje/libs/proto/experiments3/" -*- Compilation started at Mon May 19 20:28:11 bjam composed_xfrm_failure warning: Graph library does not contain optional GraphML reader. note: to enable GraphML support, set EXPAT_INCLUDE and EXPAT_LIBPATH to the note: directories containing the Expat headers and libraries, respectively. warning: skipping optional Message Passing Interface (MPI) library. note: to enable MPI support, add "using mpi ;" to user-config.jam. note: to suppress this message, pass "--without-mpi" to bjam. note: otherwise, you can safely ignore this message. Building Boost.Regex with the optional Unicode/ICU support disabled. Please refer to the Boost.Regex documentation for more information (don't panic: this is a strictly optional feature). ...patience... ...found 719 targets... ...updating 2 targets... gcc.compile.c++ ../../../../../bin.v2/sandbox/lje/libs/proto/experiments3/composed_xfrm_failure.test/gcc-4.1/debug/link-static/composed_xfrm_failure.o composed_xfrm_failure.cpp: In function 'int main()': composed_xfrm_failure.cpp:130: error: no match for call to '(type_xfrm_i1_to_i0) (boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<type_i<1u> >, 0l>, int&, int&)' ./../../../../boost/proto/transform/impl.hpp:87: note: candidates are: typename boost::proto::apply_transform<PrimitiveTransform, Expr&, State&, Data&>::result_type boost::proto::transform<PrimitiveTransform, Base>::operator()(Expr&, State&, Data&) const [with Expr = boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<type_i<1u> >, 0l>, State = int, Data = int, PrimitiveTransform = boost::proto::when<boost::proto::op::terminal<type_i<1u> >, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<type_i<0u> >, 0l> ()(boost::proto::_value)>, Base = boost::proto::transform_base] ../../../../../boost/proto/transform/impl.hpp:94: note: typename boost::proto::apply_transform<PrimitiveTransform, Expr&, const State&, Data&>::result_type boost::proto::transform<PrimitiveTransform, Base>::operator()(Expr&, const State&, Data&) const [with Expr = boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<type_i<1u> >, 0l>, State = int, Data = int, PrimitiveTransform = boost::proto::when<boost::proto::op::terminal<type_i<1u> >, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<type_i<0u> >, 0l> ()(boost::proto::_value)>, Base = boost::proto::transform_base] "/usr/bin/g++-4.1" -ftemplate-depth-128 -O0 -fno-inline -Wall -g -ftemplate-depth-1024 -DBOOST_ALL_NO_LIB=1 -DBOOST_TEST_NO_AUTO_LINK=1 -I"../../../../.." -I"../../../../functional/factory" -I"../../../../functional/forward" -I"../../../../lje" -I"../../../../.." -c -o "../../../../../bin.v2/sandbox/lje/libs/proto/experiments3/composed_xfrm_failure.test/gcc-4.1/debug/link-static/composed_xfrm_failure.o" "composed_xfrm_failure.cpp" ...failed gcc.compile.c++ ../../../../../bin.v2/sandbox/lje/libs/proto/experiments3/composed_xfrm_failure.test/gcc-4.1/debug/link-static/composed_xfrm_failure.o... ...failed updating 1 target... ...skipped 1 target... Compilation exited abnormally with code 1 at Mon May 19 20:28:15 project sandbox : requirements <include>lje&&.. <include>functional/forward <include>functional/factory : usage-requirements <include>lje&&.. <include>functional/forward <include>functional/factory : default-build debug ; rule run-utf ( name : other-sources * : requirements * ) #Purpose: # Short-hand for linking with boost_unit_test_framework { return [ run $(name).cpp $(other-sources) $(BOOST_ROOT)/libs/test/build//boost_unit_test_framework/<link>static : : : $(requirements) <define>CONTAINER_SINGLE_OBJ_ID ] ; } #cpreproc test.cpreproc # : test.cpp # ;

Larry Evans wrote:
On 05/19/08 18:51, Eric Niebler wrote:
Um, does this mean you're using the proto/v4 branch?
Yes.
Are you still having problems, or have they gone away?
They're still there.
Can you send a compiler error and steps to repro? 'Cause it works over here.
The attachment on 1st post has '#if 1' around line 117. That should produce the error. The 2nd post's attachment has '#if 0' and doesn't produce an error. When you run, do you use '#if 1' or not?
The complete bjam output of 2nd post's attachment with '#if 1' is attached as bjam.out.
Ah, you're using gcc. I see the error now. I'm sorry to say this behavior is by-design -- at least until we get rvalue references -- although there are simple work-arounds. Let me explain. A Proto transform takes an expression tree as its first argument. The signature is something like this: // take expr, state and data by non-const ref template<class Expr, class State, class Data> typename result<void(Expr &, State &, Data &)>::type operator()(Expr &expr, State &state, Data &data) const // an overload for a const state parameter. template<class Expr, class State, class Data> typename result<void(Expr &, State const &, Data &)>::type operator()(Expr &expr, State const &state, Data &data) const Note that expressions are taken by non-const reference. They must be lvalues or const-qualified rvalues. That's usually the case, but not for your code. (The data parameter is handled similarly, but there are other overloads so you don't have to specify it.) You might think I could just add an overload that takes an expression by const reference to solve the problem. But that introduces another. To do overload resolution, the compiler would need to calculate the return type for both overloads, and for some expressions, the return type calculation will fail if the expression is const-qualified. (A transform could mutate an expression tree in-place. The expression tree had better not be const.) So even if you never actually pass a const expression tree, the mere presence of the overload will cause the compile to fail. Very frustrating. So that's the reason why. You can work around the error by making sure you pass only lvalue expression trees or const-qualified rvalue expression trees to transforms. You can do that by converting a non-const rvalue into a const lvalue by passing it through a dummy as_lvalue() function like: template<class T> T const & as_lvalue(T const &t) { return t; } When I do that, I hit another error in your code having to do with an ambiguous conversion sequence. Doesn't look like a Proto problem, though. HTH, -- Eric Niebler Boost Consulting www.boost-consulting.com
participants (2)
-
Eric Niebler
-
Larry Evans