Opened 10 years ago
Last modified 8 years ago
#7996 new Bugs
phoenix::bind does not protoify the bound arguments
Reported by: | Andrey Semashev | Owned by: | Thomas Heller |
---|---|---|---|
Milestone: | To Be Determined | Component: | phoenix |
Version: | Boost Release Branch | Severity: | Problem |
Keywords: | phoenix bind proto log | Cc: |
Description
I have a problem with Boost.Phoenix v3 bind implementation when used with attribute keywords from Boost.Log. For some reason phoenix::bind does not apply proto::detail::protoify to the bound arguments which breaks compilation of some formatting expressions in Boost.Log.
Here's an example:
#include <boost/phoenix.hpp> #include <boost/log/trivial.hpp> #include <boost/log/expressions.hpp> #include <boost/log/utility/value_ref.hpp> namespace logging = boost::log; namespace expr = boost::log::expressions; namespace phoenix = boost::phoenix; // Custom severity level formatting function std::string severity_level_as_urgency( logging::value_ref< logging::trivial::severity_level, logging::trivial::tag::severity > const& level) { if (!level || level.get() == logging::trivial::info) return "normal"; logging::trivial::severity_level lvl = level.get(); if (lvl < logging::trivial::info) return "low"; else return "critical"; } int main(int, char*[]) { logging::formatter fmt = expr::stream << boost::phoenix::bind(&severity_level_as_urgency, logging::trivial::severity); return 0; }
The example creates a formatter function object that should call severity_level_as_urgency function to convert the severity level to string and put its result into a stream.
trivial::severity is a keyword of type expr::attribute_keyword< ... >. Keywords themselves should never actually be embedded into phoenix expressions, instead I have attribute_actor that implements all the necessary work to extract attribute values. I have specialized proto::detail::protoify template for attribute_keyword (including references and reference_wrappers thereof) so that it is automatically converted to attribute_actor whenever it participates in expressions. But it doesn't work with the above code, Boost.Phoenix embeds attribute_keyword as is into the expression. This results in the error I attached to the ticket.
I realize that proto::detail::protoify is not for public use and may not be intended for my use case but I did not find any other way to implement what I described. Anyway, I think bind should treat bound arguments as child subexpressions and protoify them.
To compile the test code you will have to checkout Boost.Log from SVN:
svn co https://boost-log.svn.sourceforge.net/svnroot/boost-log/branches/bleeding-edge -r 822 boost-log
Then the relevant directories have to be linked/copied into the Boost tree.
PS: The issue came from the mailing list:
Attachments (1)
Change History (11)
by , 10 years ago
Attachment: | build_error.txt added |
---|
follow-up: 2 comment:1 by , 10 years ago
Hi Andrey,
I am not sure what the problem here *exactly* is. I just checked the code of phoenix bind and all other phoenix expressions, they never use boost::proto::detail::protoify, the use the regular and document boost::proto::make_expr functionality. I am not sure who to blame here. However i think it rather is Boost.Log in this case, as phoenix uses official and document functions of proto. This means i needed to change every phoenix expression in order to work with boost.log which uses an undocument private function out of the detail namespace of a library.
That being said, this would probably need closer investigation. I will try to take a close look next week.
comment:2 by , 10 years ago
Replying to theller:
I'm by far not an expert in Boost.Proto but as far as I understand protoify is used internally by Boost.Proto to envelop objects participating in template expressions into Boost.Proto expression tree structures. In particular this is done to all terminals, and this behavior is used by Boost.Log to transparently convert all attribute_keywords to attribute_actors.
Boost.Phoenix doesn't use protoify directly, but it does so through some public interface of Boost.Proto (which is probably make_expr, I don't know for sure). My guess is that phoenix::bind doesn't treat the bound arguments the same way Boost.Phoenix treats other terminals in template expressions. This results in bound arguments not being enveloped into Boost.Proto terminal structures and consequently it doesn't invoke protoify and breaks Boost.Log.
I will be happy to use a public interface of Boost.Proto or Boost.Phoenix to achieve what I need. I just didn't find such an interface. Please, tell me if there is one.
follow-up: 5 comment:4 by , 9 years ago
I am going to start to look at this problem. My first reaction is that if Thomas did not know an answer, and he wrote version 3 of phoenix to use proto, then I am going to have to do quite a lot of digging to find this one. John
comment:5 by , 9 years ago
Replying to John Fletcher <J.P.Fletcher@…>:
I am going to start to look at this problem. My first reaction is that if Thomas did not know an answer, and he wrote version 3 of phoenix to use proto, then I am going to have to do quite a lot of digging to find this one. John
This is not working.
comment:7 by , 9 years ago
Replying to John Fletcher <J.P.Fletcher@…>:
Sorry, response on the wrong item.
It was "this is not working" which was on the wrong bug trac. I have yet to start on this one. John
comment:8 by , 8 years ago
Component: | phoenix → xpressive |
---|---|
Milestone: | To Be Determined → Website 1.X |
Owner: | changed from | to
Severity: | Problem → Not Applicable |
Type: | Bugs → Library Submissions |
Version: | Boost Release Branch → Boost.Build-M3 |
Thanks so much for sharing this excellent info! I'm seeking forward to see much more posts! beececefeeeeeeec
comment:9 by , 8 years ago
Component: | xpressive → phoenix |
---|---|
Milestone: | Website 1.X → To Be Determined |
Owner: | changed from | to
Severity: | Not Applicable → Problem |
Type: | Library Submissions → Bugs |
Version: | Boost.Build-M3 → Boost Release Branch |
Compilation error